gdharness 0.12.0 → 0.12.2
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/README.md +6 -5
- package/build/cli.js +46 -8
- package/build/index.js +10 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -73,11 +73,12 @@ and integration suites run against a real engine on all three before anything is
|
|
|
73
73
|
|
|
74
74
|
What each kind of release means here:
|
|
75
75
|
|
|
76
|
-
- **Patch**:
|
|
77
|
-
corrected is a fix rather than a feature
|
|
78
|
-
how a tool stops being worth asking.
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
- **Patch**: nearly everything. An answer that was wrong is now right, and the output may change
|
|
77
|
+
shape for it, because a wrong answer corrected is a fix rather than a feature and leaving one
|
|
78
|
+
wrong to protect whoever parsed it is how a tool stops being worth asking. An addition nothing
|
|
79
|
+
has to adapt to is a patch too: a new argument, a new field, an argument reaching further than it
|
|
80
|
+
did. Ignore all of it and your calls still work.
|
|
81
|
+
- **Minor**: a new tool or a new op, meaning this does something it could not do before.
|
|
81
82
|
- **Major**: a tool, an op, an argument or a field was renamed or taken away. Nothing else earns
|
|
82
83
|
one.
|
|
83
84
|
|
package/build/cli.js
CHANGED
|
@@ -15714,7 +15714,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
15714
15714
|
},
|
|
15715
15715
|
{
|
|
15716
15716
|
name: "editor_output",
|
|
15717
|
-
description: "What the project started by editor_run has printed, as entries with a severity: the errors and warnings the engine reported, each with where it happened, and everything else as info. Answers with the counts and the verdict as well as the entries. A run that has quit still answers here, with running false and its exit code, until the next one starts.",
|
|
15717
|
+
description: "What the project started by editor_run has printed, as entries with a severity: the errors and warnings the engine reported, each with where it happened, and everything else as info. Answers with the counts and the verdict as well as the entries. A run that has quit still answers here, with running false and its exit code, until the next one starts. A run this server started also answers with transcript, the file both its streams are written to: uncapped, written while the run is going, and the thing to read or tail for a long run rather than the engine's own log, which every engine start rotates away.",
|
|
15718
15718
|
parameters: {
|
|
15719
15719
|
severity: {
|
|
15720
15720
|
type: "string",
|
|
@@ -38002,6 +38002,13 @@ class GodotServer {
|
|
|
38002
38002
|
limit: readPositiveNumber(args, "limit") ?? 200
|
|
38003
38003
|
});
|
|
38004
38004
|
const halt = run.throughEditor ? this.dapClient?.whereItStopped() ?? null : null;
|
|
38005
|
+
const notes = [];
|
|
38006
|
+
if (run.endedUnwatched === true) {
|
|
38007
|
+
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.");
|
|
38008
|
+
}
|
|
38009
|
+
if (run.transcript !== null && selected.omitted > 0) {
|
|
38010
|
+
notes.push(`Everything this run has printed is in ${run.transcript}, uncapped and still being written.`);
|
|
38011
|
+
}
|
|
38005
38012
|
return this.jsonTextResponse({
|
|
38006
38013
|
running: stillRunning(run),
|
|
38007
38014
|
exitCode: run.exitCode,
|
|
@@ -38013,7 +38020,8 @@ class GodotServer {
|
|
|
38013
38020
|
heldAt: halt,
|
|
38014
38021
|
endedUnwatched: run.endedUnwatched === true ? true : undefined,
|
|
38015
38022
|
project: !run.throughEditor && run.process === null ? run.projectPath ?? undefined : undefined,
|
|
38016
|
-
|
|
38023
|
+
transcript: run.transcript ?? undefined,
|
|
38024
|
+
note: notes.length > 0 ? notes.join(" ") : undefined,
|
|
38017
38025
|
omitted: selected.omitted,
|
|
38018
38026
|
entries: selected.entries
|
|
38019
38027
|
});
|
|
@@ -39477,6 +39485,9 @@ async function enablePlugins(engine, projectPath, names) {
|
|
|
39477
39485
|
}
|
|
39478
39486
|
return outcomes;
|
|
39479
39487
|
}
|
|
39488
|
+
function autoloadIsOurs(named) {
|
|
39489
|
+
return named === null || named === `res://${RUNTIME_AUTOLOAD.path}`;
|
|
39490
|
+
}
|
|
39480
39491
|
async function setRuntime(engine, projectPath, on) {
|
|
39481
39492
|
return on ? await runOperation2(engine, "add_autoload", { name: RUNTIME_AUTOLOAD.name, path: `res://${RUNTIME_AUTOLOAD.path}`, enabled: true }, projectPath) : await runOperation2(engine, "remove_autoload", { name: RUNTIME_AUTOLOAD.name }, projectPath);
|
|
39482
39493
|
}
|
|
@@ -39533,8 +39544,12 @@ function inspectProject(projectPath) {
|
|
|
39533
39544
|
}
|
|
39534
39545
|
}
|
|
39535
39546
|
const autoload = settings["autoload"];
|
|
39536
|
-
const
|
|
39547
|
+
const registered = autoload === undefined ? undefined : readString(autoload, RUNTIME_AUTOLOAD.name);
|
|
39548
|
+
const runtimeAutoload = typeof registered === "string";
|
|
39549
|
+
const runtimeAutoloadPath = typeof registered === "string" ? registered.replace(/^\*/, "") : null;
|
|
39537
39550
|
const named = autoloadPaths(settings);
|
|
39551
|
+
const loaderEntry = [...named].find(([entry, path]) => entry !== RUNTIME_AUTOLOAD.name && path !== RUNTIME_AUTOLOAD.path && path.toLowerCase().includes("gdharness")) ?? null;
|
|
39552
|
+
const runtimeLoaderAutoload = loaderEntry === null ? null : { name: loaderEntry[0], path: loaderEntry[1] };
|
|
39538
39553
|
const tracked = trackedByGit(projectPath, [...named.values()]);
|
|
39539
39554
|
for (const [name, path] of named) {
|
|
39540
39555
|
if (tracked !== null && !tracked.has(path) && existsSync7(join8(projectPath, path))) {
|
|
@@ -39553,6 +39568,8 @@ function inspectProject(projectPath) {
|
|
|
39553
39568
|
addons,
|
|
39554
39569
|
pluginsEnabled,
|
|
39555
39570
|
runtimeAutoload,
|
|
39571
|
+
runtimeAutoloadPath,
|
|
39572
|
+
runtimeLoaderAutoload,
|
|
39556
39573
|
staleClasses,
|
|
39557
39574
|
classCacheExists: cached !== null,
|
|
39558
39575
|
problems
|
|
@@ -39839,6 +39856,24 @@ function said2(outcome, what) {
|
|
|
39839
39856
|
console.error(` engine ${entry.severity}: ${entry.text}`);
|
|
39840
39857
|
}
|
|
39841
39858
|
}
|
|
39859
|
+
async function registerRuntime(godot, projectPath) {
|
|
39860
|
+
const report = inspectProject(projectPath);
|
|
39861
|
+
const named = report.runtimeAutoloadPath;
|
|
39862
|
+
const loader = report.runtimeLoaderAutoload;
|
|
39863
|
+
if (named === null && loader !== null) {
|
|
39864
|
+
console.log(`${loader.name} autoload already names res://${loader.path}, which is this project bringing the runtime up its own way, so ${RUNTIME_AUTOLOAD.name} was not added: a second entry would come up beside it without whatever that file refuses. If it is not a loader, add ${RUNTIME_AUTOLOAD.name} yourself.`);
|
|
39865
|
+
return;
|
|
39866
|
+
}
|
|
39867
|
+
if (autoloadIsOurs(named)) {
|
|
39868
|
+
said2(await setRuntime(godot, projectPath, true), "registering the runtime autoload");
|
|
39869
|
+
console.log(`${RUNTIME_AUTOLOAD.name} autoload registered at res://${RUNTIME_AUTOLOAD.path}`);
|
|
39870
|
+
return;
|
|
39871
|
+
}
|
|
39872
|
+
console.log(`${RUNTIME_AUTOLOAD.name} autoload left at ${named}, which this project registers itself`);
|
|
39873
|
+
if (!existsSync13(join17(projectPath, (named ?? "").replace(/^res:\/\//, "")))) {
|
|
39874
|
+
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}`);
|
|
39875
|
+
}
|
|
39876
|
+
}
|
|
39842
39877
|
var SETUP_FLAGS = new Set(["--runtime", "--no-runtime", "--no-connect", "--no-skill", "--json", "--yes"]);
|
|
39843
39878
|
function namedHarnesses() {
|
|
39844
39879
|
const flags = args.filter((arg) => arg.startsWith("--") && !SETUP_FLAGS.has(arg));
|
|
@@ -39941,8 +39976,7 @@ async function setup() {
|
|
|
39941
39976
|
console.log(`${name}: ${outcome.ok ? String(outcome.payload["action"]) : "failed"}`);
|
|
39942
39977
|
}
|
|
39943
39978
|
if (runtime) {
|
|
39944
|
-
|
|
39945
|
-
console.log(`${RUNTIME_AUTOLOAD.name} autoload registered`);
|
|
39979
|
+
await registerRuntime(godot, projectPath);
|
|
39946
39980
|
}
|
|
39947
39981
|
const classes = await runOperation(godot, "refresh_class_cache", {}, projectPath);
|
|
39948
39982
|
said2(classes, "rebuilding the class list");
|
|
@@ -40042,7 +40076,7 @@ async function upgrade() {
|
|
|
40042
40076
|
said2(outcome, `enabling ${EDITOR_PLUGINS[index] ?? ""}`);
|
|
40043
40077
|
}
|
|
40044
40078
|
if (before.runtimeAutoload) {
|
|
40045
|
-
|
|
40079
|
+
await registerRuntime(godot, projectPath);
|
|
40046
40080
|
}
|
|
40047
40081
|
said2(await runOperation(godot, "refresh_class_cache", {}, projectPath), "rebuilding the class list");
|
|
40048
40082
|
const launch = launchFor(version, godot.godotPath, projectPath);
|
|
@@ -40092,8 +40126,12 @@ async function runtime3() {
|
|
|
40092
40126
|
}
|
|
40093
40127
|
const projectPath = projectArgument(2);
|
|
40094
40128
|
const godot = await engine();
|
|
40095
|
-
|
|
40096
|
-
|
|
40129
|
+
if (state === "on") {
|
|
40130
|
+
await registerRuntime(godot, projectPath);
|
|
40131
|
+
return;
|
|
40132
|
+
}
|
|
40133
|
+
said2(await setRuntime(godot, projectPath, false), "turning the runtime off");
|
|
40134
|
+
console.log(`${RUNTIME_AUTOLOAD.name} autoload removed`);
|
|
40097
40135
|
}
|
|
40098
40136
|
async function classes() {
|
|
40099
40137
|
const projectPath = projectArgument(1);
|
package/build/index.js
CHANGED
|
@@ -28518,7 +28518,7 @@ var TOOL_SPECS = [
|
|
|
28518
28518
|
},
|
|
28519
28519
|
{
|
|
28520
28520
|
name: "editor_output",
|
|
28521
|
-
description: "What the project started by editor_run has printed, as entries with a severity: the errors and warnings the engine reported, each with where it happened, and everything else as info. Answers with the counts and the verdict as well as the entries. A run that has quit still answers here, with running false and its exit code, until the next one starts.",
|
|
28521
|
+
description: "What the project started by editor_run has printed, as entries with a severity: the errors and warnings the engine reported, each with where it happened, and everything else as info. Answers with the counts and the verdict as well as the entries. A run that has quit still answers here, with running false and its exit code, until the next one starts. A run this server started also answers with transcript, the file both its streams are written to: uncapped, written while the run is going, and the thing to read or tail for a long run rather than the engine's own log, which every engine start rotates away.",
|
|
28522
28522
|
parameters: {
|
|
28523
28523
|
severity: {
|
|
28524
28524
|
type: "string",
|
|
@@ -30784,6 +30784,13 @@ class GodotServer {
|
|
|
30784
30784
|
limit: readPositiveNumber(args, "limit") ?? 200
|
|
30785
30785
|
});
|
|
30786
30786
|
const halt = run.throughEditor ? this.dapClient?.whereItStopped() ?? null : null;
|
|
30787
|
+
const notes = [];
|
|
30788
|
+
if (run.endedUnwatched === true) {
|
|
30789
|
+
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.");
|
|
30790
|
+
}
|
|
30791
|
+
if (run.transcript !== null && selected.omitted > 0) {
|
|
30792
|
+
notes.push(`Everything this run has printed is in ${run.transcript}, uncapped and still being written.`);
|
|
30793
|
+
}
|
|
30787
30794
|
return this.jsonTextResponse({
|
|
30788
30795
|
running: stillRunning(run),
|
|
30789
30796
|
exitCode: run.exitCode,
|
|
@@ -30795,7 +30802,8 @@ class GodotServer {
|
|
|
30795
30802
|
heldAt: halt,
|
|
30796
30803
|
endedUnwatched: run.endedUnwatched === true ? true : undefined,
|
|
30797
30804
|
project: !run.throughEditor && run.process === null ? run.projectPath ?? undefined : undefined,
|
|
30798
|
-
|
|
30805
|
+
transcript: run.transcript ?? undefined,
|
|
30806
|
+
note: notes.length > 0 ? notes.join(" ") : undefined,
|
|
30799
30807
|
omitted: selected.omitted,
|
|
30800
30808
|
entries: selected.entries
|
|
30801
30809
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gdharness",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.2",
|
|
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",
|