gdharness 0.12.15 → 0.12.17
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 +28 -5
- package/build/index.js +25 -4
- package/package.json +1 -1
package/build/cli.js
CHANGED
|
@@ -7467,6 +7467,13 @@ function addonMismatch(addonVersion, serverVersion) {
|
|
|
7467
7467
|
}
|
|
7468
7468
|
return `${both} Restart it with editor_launch restart to pick the new one up.`;
|
|
7469
7469
|
}
|
|
7470
|
+
function markIfStale(answer, addonVersion, serverVersion) {
|
|
7471
|
+
const staleNote = addonMismatch(addonVersion, serverVersion);
|
|
7472
|
+
if (staleNote === undefined || typeof answer !== "object" || answer === null || Array.isArray(answer)) {
|
|
7473
|
+
return answer;
|
|
7474
|
+
}
|
|
7475
|
+
return { ...answer, addonIsStale: true, staleNote };
|
|
7476
|
+
}
|
|
7470
7477
|
var DEBUG_MODE, GODOT_DEBUG_MODE_DEFAULT, SERVER_VERSION, UNVERSIONED = "addon from before versions were reported";
|
|
7471
7478
|
var init_server_version = __esm(() => {
|
|
7472
7479
|
init_update_check();
|
|
@@ -36159,6 +36166,16 @@ function writeRunRecord(record) {
|
|
|
36159
36166
|
mkdirSync6(runsDirectory(), { recursive: true });
|
|
36160
36167
|
writeFileSync8(recordPath(), JSON.stringify(record, null, 2), "utf8");
|
|
36161
36168
|
}
|
|
36169
|
+
function recordRunEnded(pid, exitCode) {
|
|
36170
|
+
const path = recordPath();
|
|
36171
|
+
const record = recordAt(path);
|
|
36172
|
+
if (record === null || record.pid !== pid) {
|
|
36173
|
+
return;
|
|
36174
|
+
}
|
|
36175
|
+
try {
|
|
36176
|
+
writeFileSync8(path, JSON.stringify({ ...record, exitCode }, null, 2), "utf8");
|
|
36177
|
+
} catch {}
|
|
36178
|
+
}
|
|
36162
36179
|
function readRunRecord() {
|
|
36163
36180
|
for (const path of recordPaths()) {
|
|
36164
36181
|
const record = recordAt(path);
|
|
@@ -36192,7 +36209,8 @@ function recordAt(path) {
|
|
|
36192
36209
|
startedAt,
|
|
36193
36210
|
projectPath: typeof fields["projectPath"] === "string" ? fields["projectPath"] : "",
|
|
36194
36211
|
arguments: Array.isArray(args) ? args.filter((value) => typeof value === "string") : [],
|
|
36195
|
-
...typeof fields["command"] === "string" ? { command: fields["command"] } : {}
|
|
36212
|
+
...typeof fields["command"] === "string" ? { command: fields["command"] } : {},
|
|
36213
|
+
...typeof fields["exitCode"] === "number" ? { exitCode: fields["exitCode"] } : {}
|
|
36196
36214
|
};
|
|
36197
36215
|
}
|
|
36198
36216
|
function runningAs(pid) {
|
|
@@ -38006,6 +38024,9 @@ class GodotServer {
|
|
|
38006
38024
|
this.logDebug(`Godot process exited with code ${code ?? "none"}`);
|
|
38007
38025
|
log.finish();
|
|
38008
38026
|
started.exitCode = code ?? -1;
|
|
38027
|
+
if (started.pid !== null) {
|
|
38028
|
+
recordRunEnded(started.pid, started.exitCode);
|
|
38029
|
+
}
|
|
38009
38030
|
});
|
|
38010
38031
|
child.on("error", (err) => {
|
|
38011
38032
|
console.error("Failed to start Godot process:", err);
|
|
@@ -38110,8 +38131,8 @@ class GodotServer {
|
|
|
38110
38131
|
this.drainTranscript(adopted);
|
|
38111
38132
|
if (!alive(record.pid) || !couldStillBeTheRecordedRun(record)) {
|
|
38112
38133
|
adopted.log.finish();
|
|
38113
|
-
adopted.exitCode = null;
|
|
38114
|
-
adopted.endedUnwatched =
|
|
38134
|
+
adopted.exitCode = record.exitCode ?? null;
|
|
38135
|
+
adopted.endedUnwatched = record.exitCode === undefined;
|
|
38115
38136
|
}
|
|
38116
38137
|
this.activeProcess = adopted;
|
|
38117
38138
|
return adopted;
|
|
@@ -38314,7 +38335,7 @@ class GodotServer {
|
|
|
38314
38335
|
]);
|
|
38315
38336
|
}
|
|
38316
38337
|
try {
|
|
38317
|
-
return this.jsonTextResponse(await this.godotBridge.invokeTool(toolName, args));
|
|
38338
|
+
return this.jsonTextResponse(markIfStale(await this.godotBridge.invokeTool(toolName, args), this.godotBridge.getStatus().addonVersion, SERVER_VERSION));
|
|
38318
38339
|
} catch (error) {
|
|
38319
38340
|
return this.createErrorResponse(`The editor answered ${toolName} with an error: ${errorMessage(error)}`);
|
|
38320
38341
|
}
|
|
@@ -39897,7 +39918,9 @@ that is running, and the project on disk. ${TOOL_SPECS.length} tools, named \`do
|
|
|
39897
39918
|
running games. There is no ambient project.
|
|
39898
39919
|
- \`editor_status\` says whether an editor is connected and whether its addon matches the server.
|
|
39899
39920
|
\`addonIsStale\` means they differ, and \`staleNote\` says which half is behind: an editor that
|
|
39900
|
-
needs restarting, or a server that needs reconnecting in your harness.
|
|
39921
|
+
needs restarting, or a server that needs reconnecting in your harness. Every answer that came
|
|
39922
|
+
from the editor carries the same two when they differ, so a stale addon cannot answer quietly:
|
|
39923
|
+
believe a restart over a diagnostic that arrived with them.
|
|
39901
39924
|
- Start the game with \`editor_run start\`, never by spawning an engine. The editor plays it, so
|
|
39902
39925
|
its debugger holds it, which is what gives the \`debug_*\` tools something to talk to. Its answer
|
|
39903
39926
|
says under \`runtime\` whether the game can be talked to yet; when it cannot, \`mayYetAnnounce\`
|
package/build/index.js
CHANGED
|
@@ -10040,6 +10040,13 @@ function addonMismatch(addonVersion, serverVersion) {
|
|
|
10040
10040
|
}
|
|
10041
10041
|
return `${both} Restart it with editor_launch restart to pick the new one up.`;
|
|
10042
10042
|
}
|
|
10043
|
+
function markIfStale(answer, addonVersion, serverVersion) {
|
|
10044
|
+
const staleNote = addonMismatch(addonVersion, serverVersion);
|
|
10045
|
+
if (staleNote === undefined || typeof answer !== "object" || answer === null || Array.isArray(answer)) {
|
|
10046
|
+
return answer;
|
|
10047
|
+
}
|
|
10048
|
+
return { ...answer, addonIsStale: true, staleNote };
|
|
10049
|
+
}
|
|
10043
10050
|
|
|
10044
10051
|
// src/issues.ts
|
|
10045
10052
|
var NEW_ISSUE = "https://github.com/Aureliolo/gdharness/issues/new";
|
|
@@ -27841,6 +27848,16 @@ function writeRunRecord(record) {
|
|
|
27841
27848
|
mkdirSync3(runsDirectory(), { recursive: true });
|
|
27842
27849
|
writeFileSync4(recordPath(), JSON.stringify(record, null, 2), "utf8");
|
|
27843
27850
|
}
|
|
27851
|
+
function recordRunEnded(pid, exitCode) {
|
|
27852
|
+
const path = recordPath();
|
|
27853
|
+
const record = recordAt(path);
|
|
27854
|
+
if (record === null || record.pid !== pid) {
|
|
27855
|
+
return;
|
|
27856
|
+
}
|
|
27857
|
+
try {
|
|
27858
|
+
writeFileSync4(path, JSON.stringify({ ...record, exitCode }, null, 2), "utf8");
|
|
27859
|
+
} catch {}
|
|
27860
|
+
}
|
|
27844
27861
|
function readRunRecord() {
|
|
27845
27862
|
for (const path of recordPaths()) {
|
|
27846
27863
|
const record = recordAt(path);
|
|
@@ -27874,7 +27891,8 @@ function recordAt(path) {
|
|
|
27874
27891
|
startedAt,
|
|
27875
27892
|
projectPath: typeof fields["projectPath"] === "string" ? fields["projectPath"] : "",
|
|
27876
27893
|
arguments: Array.isArray(args) ? args.filter((value) => typeof value === "string") : [],
|
|
27877
|
-
...typeof fields["command"] === "string" ? { command: fields["command"] } : {}
|
|
27894
|
+
...typeof fields["command"] === "string" ? { command: fields["command"] } : {},
|
|
27895
|
+
...typeof fields["exitCode"] === "number" ? { exitCode: fields["exitCode"] } : {}
|
|
27878
27896
|
};
|
|
27879
27897
|
}
|
|
27880
27898
|
function runningAs(pid) {
|
|
@@ -30789,6 +30807,9 @@ class GodotServer {
|
|
|
30789
30807
|
this.logDebug(`Godot process exited with code ${code ?? "none"}`);
|
|
30790
30808
|
log.finish();
|
|
30791
30809
|
started.exitCode = code ?? -1;
|
|
30810
|
+
if (started.pid !== null) {
|
|
30811
|
+
recordRunEnded(started.pid, started.exitCode);
|
|
30812
|
+
}
|
|
30792
30813
|
});
|
|
30793
30814
|
child.on("error", (err) => {
|
|
30794
30815
|
console.error("Failed to start Godot process:", err);
|
|
@@ -30893,8 +30914,8 @@ class GodotServer {
|
|
|
30893
30914
|
this.drainTranscript(adopted);
|
|
30894
30915
|
if (!alive(record.pid) || !couldStillBeTheRecordedRun(record)) {
|
|
30895
30916
|
adopted.log.finish();
|
|
30896
|
-
adopted.exitCode = null;
|
|
30897
|
-
adopted.endedUnwatched =
|
|
30917
|
+
adopted.exitCode = record.exitCode ?? null;
|
|
30918
|
+
adopted.endedUnwatched = record.exitCode === undefined;
|
|
30898
30919
|
}
|
|
30899
30920
|
this.activeProcess = adopted;
|
|
30900
30921
|
return adopted;
|
|
@@ -31097,7 +31118,7 @@ class GodotServer {
|
|
|
31097
31118
|
]);
|
|
31098
31119
|
}
|
|
31099
31120
|
try {
|
|
31100
|
-
return this.jsonTextResponse(await this.godotBridge.invokeTool(toolName, args));
|
|
31121
|
+
return this.jsonTextResponse(markIfStale(await this.godotBridge.invokeTool(toolName, args), this.godotBridge.getStatus().addonVersion, SERVER_VERSION));
|
|
31101
31122
|
} catch (error) {
|
|
31102
31123
|
return this.createErrorResponse(`The editor answered ${toolName} with an error: ${errorMessage(error)}`);
|
|
31103
31124
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gdharness",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.17",
|
|
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",
|