gdharness 1.2.13 → 1.2.15
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 +49 -6
- package/build/godot/operations/classdb_queries.gd +27 -2
- package/build/godot/operations/import_pipeline.gd +10 -1
- package/build/godot/operations/project_config.gd +7 -1
- package/build/godot/operations/project_diagnostics.gd +12 -28
- package/build/index.js +49 -5
- package/package.json +1 -1
package/build/cli.js
CHANGED
|
@@ -11005,7 +11005,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
11005
11005
|
{
|
|
11006
11006
|
name: "project_settings",
|
|
11007
11007
|
title: "Project settings",
|
|
11008
|
-
description: "Reads or writes project.godot: settings, autoloads, the main scene, input actions, plugins and audio buses. A write with an editor open on the project is handed to the editor, which takes the settings the write changed or names from the file (named under editorAdopted), including a setting the file already held, since the editor can hold another value after the file was put back, or reloads the bus layout, so it answers the new values and does not save the old ones back over them. editorNote is an editor that could not take the write, one on an addon from before this, which still holds the old values until editor_launch restart. An enabled plugin's code still loads on the editor's next start.",
|
|
11008
|
+
description: "Reads or writes project.godot: settings, autoloads, the main scene, input actions, plugins and audio buses. A write with an editor open on the project is handed to the editor, which takes the settings the write changed or names from the file (named under editorAdopted), including a setting the file already held, since the editor can hold another value after the file was put back, or reloads the bus layout, so it answers the new values and does not save the old ones back over them. editorNote is an editor that could not take the write, one on an addon from before this, which still holds the old values until editor_launch restart. An enabled plugin's code still loads on the editor's next start. set answers old_value and new_value, with was_new true when project.godot did not set the setting before, and was_default true when what it held was the engine's own default, which old_value then is.",
|
|
11009
11009
|
parameters: {
|
|
11010
11010
|
projectPath: PROJECT_PATH,
|
|
11011
11011
|
setting: { type: "string", description: 'Setting path, such as "display/window/size/viewport_width".' },
|
|
@@ -11708,7 +11708,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
11708
11708
|
},
|
|
11709
11709
|
check: {
|
|
11710
11710
|
effect: "additive",
|
|
11711
|
-
summary: "boot headless, quit after a few frames, and report the verdict",
|
|
11711
|
+
summary: "boot headless, quit after a few frames, and report the verdict. booted is that verdict rather than whether the game came up: true only for a run that quit on its own within timeoutMs, exited 0 and printed no error, so a game that reached _ready and then raised an error answers false. hung is a run killed at timeoutMs, and errors and warnings count what it printed, which comes back under entries with repeats folded together",
|
|
11712
11712
|
requires: ["projectPath"]
|
|
11713
11713
|
},
|
|
11714
11714
|
wait: {
|
|
@@ -12889,6 +12889,18 @@ function prefixIssues(path, issues) {
|
|
|
12889
12889
|
function unwrapMessage(message) {
|
|
12890
12890
|
return typeof message === "string" ? message : message?.message;
|
|
12891
12891
|
}
|
|
12892
|
+
function sizeCaps(defChecks) {
|
|
12893
|
+
const caps = [];
|
|
12894
|
+
for (const ch of defChecks ?? []) {
|
|
12895
|
+
const d = ch._zod.def;
|
|
12896
|
+
if (!/_(length|size)$|_equals$/.test(d.check))
|
|
12897
|
+
break;
|
|
12898
|
+
const max = d.maximum ?? d.length ?? d.size;
|
|
12899
|
+
if (max >= 0)
|
|
12900
|
+
caps.push([max, ch]);
|
|
12901
|
+
}
|
|
12902
|
+
return caps;
|
|
12903
|
+
}
|
|
12892
12904
|
function attachSchema(issues, start, inst) {
|
|
12893
12905
|
var _a;
|
|
12894
12906
|
for (let i = start;i < issues.length; i++) {
|
|
@@ -13926,7 +13938,7 @@ var init_versions = __esm(() => {
|
|
|
13926
13938
|
version = {
|
|
13927
13939
|
major: 4,
|
|
13928
13940
|
minor: 6,
|
|
13929
|
-
patch:
|
|
13941
|
+
patch: 7
|
|
13930
13942
|
};
|
|
13931
13943
|
});
|
|
13932
13944
|
|
|
@@ -14052,6 +14064,28 @@ function isValidJWT(token, algorithm = null) {
|
|
|
14052
14064
|
return false;
|
|
14053
14065
|
}
|
|
14054
14066
|
}
|
|
14067
|
+
function capSize(inst, size) {
|
|
14068
|
+
const caps = sizeCaps(inst._zod.def.checks);
|
|
14069
|
+
if (!caps.length)
|
|
14070
|
+
return;
|
|
14071
|
+
const cap = Math.min(...caps.map((c) => c[0]));
|
|
14072
|
+
const parse = inst._zod.parse;
|
|
14073
|
+
inst._zod.parse = (payload, ctx) => {
|
|
14074
|
+
const n = size(payload.value);
|
|
14075
|
+
if (n > cap && !ctx?.skipChecks && ctx?.direction !== "backward") {
|
|
14076
|
+
for (const [max, ch] of sizeCaps(inst._zod.def.checks)) {
|
|
14077
|
+
if (n > max && ch._zod.def.when(payload)) {
|
|
14078
|
+
const start = payload.issues.length;
|
|
14079
|
+
ch._zod.check(payload);
|
|
14080
|
+
payload.issues[start].continue = false;
|
|
14081
|
+
attachSchema(payload.issues, start, inst);
|
|
14082
|
+
return payload;
|
|
14083
|
+
}
|
|
14084
|
+
}
|
|
14085
|
+
}
|
|
14086
|
+
return parse(payload, ctx);
|
|
14087
|
+
};
|
|
14088
|
+
}
|
|
14055
14089
|
function handleArrayResult(result, final, index) {
|
|
14056
14090
|
if (result.issues.length) {
|
|
14057
14091
|
final.issues.push(...prefixIssues(index, result.issues));
|
|
@@ -14357,7 +14391,7 @@ function handleRefineResult(result, payload, input, inst) {
|
|
|
14357
14391
|
payload.issues.push(issue(_iss));
|
|
14358
14392
|
}
|
|
14359
14393
|
}
|
|
14360
|
-
var $ZodType, toStandardResult = (r, ctx) => r.issues.length ? { issues: r.issues.map((iss) => finalizeIssue(iss, ctx, config())) } : { value: r.value }, $ZodString, $ZodStringFormat, $ZodGUID, $ZodUUID, $ZodEmail, URL_BAD_FORMAT = 1, URL_UNPARSEABLE = 2, asciiTabOrNewline, $ZodURL, $ZodEmoji, $ZodNanoID, $ZodCUID, $ZodCUID2, $ZodULID, $ZodXID, $ZodKSUID, $ZodISODateTime, $ZodISODate, $ZodISOTime, $ZodISODuration, $ZodIPv4, ipv6Alphabet, $ZodIPv6, $ZodCIDRv4, $ZodCIDRv6, base64Charset, $ZodBase64, base64urlCharset, $ZodBase64URL, $ZodE164, $ZodJWT, $ZodNumber, $ZodNumberFormat, $ZodBoolean, $ZodNull, $ZodAny, $ZodUnknown, $ZodNever, $ZodArray, NO_SYMBOL_KEYS, $ZodObject, $ZodObjectJIT, $ZodUnion, $ZodDiscriminatedUnion, $ZodIntersection, $ZodRecord, $ZodEnum, $ZodLiteral, $ZodTransform, $ZodOptional, $ZodExactOptional, $ZodNullable, $ZodDefault, $ZodPrefault, $ZodNonOptional, $ZodCatch, $ZodPipe, $ZodPreprocess, $ZodReadonly, $ZodLazy, $ZodCustom;
|
|
14394
|
+
var $ZodType, toStandardResult = (r, ctx) => r.issues.length ? { issues: r.issues.map((iss) => finalizeIssue(iss, ctx, config())) } : { value: r.value }, $ZodString, $ZodStringFormat, $ZodGUID, $ZodUUID, $ZodEmail, URL_BAD_FORMAT = 1, URL_UNPARSEABLE = 2, asciiTabOrNewline, $ZodURL, $ZodEmoji, $ZodNanoID, $ZodCUID, $ZodCUID2, $ZodULID, $ZodXID, $ZodKSUID, $ZodISODateTime, $ZodISODate, $ZodISOTime, $ZodISODuration, $ZodIPv4, ipv6Alphabet, $ZodIPv6, $ZodCIDRv4, $ZodCIDRv6, base64Charset, $ZodBase64, base64urlCharset, $ZodBase64URL, $ZodE164, $ZodJWT, $ZodNumber, $ZodNumberFormat, $ZodBoolean, $ZodNull, $ZodAny, $ZodUnknown, $ZodNever, arraySize = (input) => Array.isArray(input) ? input.length : -1, $ZodArray, NO_SYMBOL_KEYS, $ZodObject, $ZodObjectJIT, $ZodUnion, $ZodDiscriminatedUnion, $ZodIntersection, $ZodRecord, $ZodEnum, $ZodLiteral, $ZodTransform, $ZodOptional, $ZodExactOptional, $ZodNullable, $ZodDefault, $ZodPrefault, $ZodNonOptional, $ZodCatch, $ZodPipe, $ZodPreprocess, $ZodReadonly, $ZodLazy, $ZodCustom;
|
|
14361
14395
|
var init_schemas = __esm(() => {
|
|
14362
14396
|
init_checks();
|
|
14363
14397
|
init_core();
|
|
@@ -14847,6 +14881,7 @@ var init_schemas = __esm(() => {
|
|
|
14847
14881
|
}
|
|
14848
14882
|
return payload;
|
|
14849
14883
|
};
|
|
14884
|
+
capSize(inst, arraySize);
|
|
14850
14885
|
});
|
|
14851
14886
|
NO_SYMBOL_KEYS = [];
|
|
14852
14887
|
$ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
@@ -40799,7 +40834,11 @@ var init_prompts = __esm(() => {
|
|
|
40799
40834
|
}
|
|
40800
40835
|
],
|
|
40801
40836
|
steps: [
|
|
40802
|
-
{
|
|
40837
|
+
{
|
|
40838
|
+
tool: "editor_status",
|
|
40839
|
+
passes: [],
|
|
40840
|
+
why: "see whether an editor is connected and its addon matches; without one the run is a game of its own, not a fault"
|
|
40841
|
+
},
|
|
40803
40842
|
{ tool: "editor_run", op: "start", passes: ["projectPath", "scene"], why: "start the run" },
|
|
40804
40843
|
{
|
|
40805
40844
|
tool: "editor_run",
|
|
@@ -40817,7 +40856,11 @@ var init_prompts = __esm(() => {
|
|
|
40817
40856
|
description: "Check the editor connection, the project health report, export validation and the import state.",
|
|
40818
40857
|
arguments: [PROJECT_PATH2],
|
|
40819
40858
|
steps: [
|
|
40820
|
-
{
|
|
40859
|
+
{
|
|
40860
|
+
tool: "editor_status",
|
|
40861
|
+
passes: [],
|
|
40862
|
+
why: "see whether an editor is connected and, if one is, whether its addon matches; no editor is no fault in the project, so leave it out of what is wrong"
|
|
40863
|
+
},
|
|
40821
40864
|
{
|
|
40822
40865
|
tool: "project_info",
|
|
40823
40866
|
passes: ["projectPath"],
|
|
@@ -283,6 +283,7 @@ func _methods_of(class_name_str: String, include_inherited: bool) -> Array[Dicti
|
|
|
283
283
|
{
|
|
284
284
|
"name": a.get("name", ""),
|
|
285
285
|
"type": a.get("type", 0),
|
|
286
|
+
"type_name": _type_name(a, "Variant"),
|
|
286
287
|
"class_name": a.get("class_name", ""),
|
|
287
288
|
"hint_string": a.get("hint_string", "")
|
|
288
289
|
}
|
|
@@ -293,7 +294,11 @@ func _methods_of(class_name_str: String, include_inherited: bool) -> Array[Dicti
|
|
|
293
294
|
"name": m.get("name", ""),
|
|
294
295
|
"args": args,
|
|
295
296
|
"return":
|
|
296
|
-
{
|
|
297
|
+
{
|
|
298
|
+
"type": return_info.get("type", 0),
|
|
299
|
+
"type_name": _type_name(return_info, "void"),
|
|
300
|
+
"class_name": return_info.get("class_name", "")
|
|
301
|
+
},
|
|
297
302
|
"flags": m.get("flags", 0),
|
|
298
303
|
"default_args": m.get("default_args", [])
|
|
299
304
|
}
|
|
@@ -302,6 +307,20 @@ func _methods_of(class_name_str: String, include_inherited: bool) -> Array[Dicti
|
|
|
302
307
|
return methods
|
|
303
308
|
|
|
304
309
|
|
|
310
|
+
# What [param info]'s type is called: its class for an object of one, and otherwise the engine's own
|
|
311
|
+
# name for the type, beside the number the engine reports, which reads as nothing without its enum.
|
|
312
|
+
# Nil is a value that can be anything when the usage says so, and [param nil_name] otherwise: void
|
|
313
|
+
# for what a method returns, and Variant for an argument or property with no type.
|
|
314
|
+
static func _type_name(info: Dictionary, nil_name: String) -> String:
|
|
315
|
+
var type: int = Read.as_int(info.get("type", 0))
|
|
316
|
+
var named: String = str(info.get("class_name", ""))
|
|
317
|
+
if type == TYPE_OBJECT and not named.is_empty():
|
|
318
|
+
return named
|
|
319
|
+
if type == TYPE_NIL:
|
|
320
|
+
return "Variant" if Read.as_int(info.get("usage", 0)) & PROPERTY_USAGE_NIL_IS_VARIANT else nil_name
|
|
321
|
+
return type_string(type)
|
|
322
|
+
|
|
323
|
+
|
|
305
324
|
func _properties_of(class_name_str: String, include_inherited: bool) -> Array[Dictionary]:
|
|
306
325
|
var properties: Array[Dictionary] = []
|
|
307
326
|
|
|
@@ -314,6 +333,7 @@ func _properties_of(class_name_str: String, include_inherited: bool) -> Array[Di
|
|
|
314
333
|
{
|
|
315
334
|
"name": p.get("name", ""),
|
|
316
335
|
"type": p.get("type", 0),
|
|
336
|
+
"type_name": _type_name(p, "Variant"),
|
|
317
337
|
"class_name": p.get("class_name", ""),
|
|
318
338
|
"hint": p.get("hint", 0),
|
|
319
339
|
"hint_string": p.get("hint_string", ""),
|
|
@@ -332,7 +352,12 @@ func _signals_of(class_name_str: String, include_inherited: bool) -> Array[Dicti
|
|
|
332
352
|
var declared_args: Array = s.get("args", [])
|
|
333
353
|
for a: Dictionary in declared_args:
|
|
334
354
|
sig_args.append(
|
|
335
|
-
{
|
|
355
|
+
{
|
|
356
|
+
"name": a.get("name", ""),
|
|
357
|
+
"type": a.get("type", 0),
|
|
358
|
+
"type_name": _type_name(a, "Variant"),
|
|
359
|
+
"class_name": a.get("class_name", "")
|
|
360
|
+
}
|
|
336
361
|
)
|
|
337
362
|
signals.append({"name": s.get("name", ""), "args": sig_args})
|
|
338
363
|
|
|
@@ -103,7 +103,16 @@ func get_import_status(params: Dictionary) -> Dictionary:
|
|
|
103
103
|
|
|
104
104
|
_tally(summary, status)
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
var answer: Dictionary = {"resources": resources, "summary": summary}
|
|
107
|
+
# A total of none reads as a walk that found nothing when the project is full of scripts and
|
|
108
|
+
# scenes, which the engine loads as they are and never imports.
|
|
109
|
+
if resource_path.is_empty() and summary["total"] == 0:
|
|
110
|
+
answer["note"] = (
|
|
111
|
+
"Nothing in this project is imported: the engine imports images, audio, fonts, models and"
|
|
112
|
+
+ " the like, found by extension or by a .import sidecar beside them, and loads scripts and"
|
|
113
|
+
+ " scenes as they are."
|
|
114
|
+
)
|
|
115
|
+
return answer
|
|
107
116
|
|
|
108
117
|
|
|
109
118
|
# Get import options for a resource
|
|
@@ -94,6 +94,11 @@ func set_project_setting(params: Dictionary) -> Dictionary:
|
|
|
94
94
|
var had_value: bool = ProjectSettings.has_setting(setting_path)
|
|
95
95
|
if had_value:
|
|
96
96
|
old_value = ProjectSettings.get_setting(setting_path)
|
|
97
|
+
# A setting the engine registers is there with its default whether or not project.godot sets it,
|
|
98
|
+
# so has_setting alone called the description of a project that had never set one an old value.
|
|
99
|
+
# At its default, the file does not set it: the engine drops a key at its default when it saves.
|
|
100
|
+
var default_value: Variant = ProjectSettings.property_get_revert(setting_path)
|
|
101
|
+
var was_default: bool = had_value and default_value != null and old_value == default_value
|
|
97
102
|
|
|
98
103
|
var final_value: Variant = _values.deserialize_value(value)
|
|
99
104
|
var wanted: int = _wanted_type(setting_path, old_value if had_value else null)
|
|
@@ -116,7 +121,8 @@ func set_project_setting(params: Dictionary) -> Dictionary:
|
|
|
116
121
|
"setting_path": setting_path,
|
|
117
122
|
"old_value": _values.serialize_value(old_value) if had_value else null,
|
|
118
123
|
"new_value": _values.serialize_value(final_value),
|
|
119
|
-
"was_new": not had_value,
|
|
124
|
+
"was_new": not had_value or was_default,
|
|
125
|
+
"was_default": was_default,
|
|
120
126
|
"saved": true,
|
|
121
127
|
}
|
|
122
128
|
|
|
@@ -30,16 +30,9 @@ func get_project_health(params: Dictionary) -> Dictionary:
|
|
|
30
30
|
if not FileAccess.file_exists("res://project.godot"):
|
|
31
31
|
details.append("Missing project.godot file")
|
|
32
32
|
deductions += 30
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
for dir: String in recommended_dirs:
|
|
37
|
-
if not DirAccess.dir_exists_absolute(ProjectSettings.globalize_path(dir)):
|
|
38
|
-
missing_dirs.append(dir)
|
|
39
|
-
|
|
40
|
-
if missing_dirs.size() > 0:
|
|
41
|
-
details.append("Consider organizing with directories: " + ", ".join(missing_dirs))
|
|
42
|
-
deductions += 2 * missing_dirs.size()
|
|
33
|
+
# No layout is asked for. A project without res://scenes, res://scripts and res://assets
|
|
34
|
+
# failed this check and lost points, while Godot's own guidance is to keep a scene's files
|
|
35
|
+
# together by feature, so the check failed projects for following the engine's advice.
|
|
43
36
|
|
|
44
37
|
checks["structure"] = {"name": "Project Structure", "passed": details.is_empty(), "details": details}
|
|
45
38
|
|
|
@@ -74,7 +67,6 @@ func get_project_health(params: Dictionary) -> Dictionary:
|
|
|
74
67
|
|
|
75
68
|
var script_files: Array[String] = _files.find_files("res://", ".gd")
|
|
76
69
|
var todo_count: int = 0
|
|
77
|
-
var empty_functions: int = 0
|
|
78
70
|
|
|
79
71
|
for script_path: String in script_files:
|
|
80
72
|
var file: FileAccess = FileAccess.open(script_path, FileAccess.READ)
|
|
@@ -84,16 +76,12 @@ func get_project_health(params: Dictionary) -> Dictionary:
|
|
|
84
76
|
|
|
85
77
|
if "# TODO" in content or "# FIXME" in content:
|
|
86
78
|
todo_count += 1
|
|
87
|
-
if "pass # " in content or content.ends_with("pass\n"):
|
|
88
|
-
empty_functions += 1
|
|
89
79
|
|
|
80
|
+
# Work noted for later, which no script fails on, so said rather than failed. A count of
|
|
81
|
+
# "empty functions" read off a script ending in `pass` went with it: a virtual left for an
|
|
82
|
+
# override to fill ends that way and is exactly right.
|
|
90
83
|
if todo_count > 0:
|
|
91
|
-
|
|
92
|
-
deductions += todo_count
|
|
93
|
-
|
|
94
|
-
if empty_functions > 0:
|
|
95
|
-
details.append(str(empty_functions) + " scripts may have empty functions")
|
|
96
|
-
deductions += empty_functions
|
|
84
|
+
recommendations.append("%d scripts have TODO or FIXME comments to look at" % todo_count)
|
|
97
85
|
|
|
98
86
|
checks["scripts"] = {
|
|
99
87
|
"name": "Scripts",
|
|
@@ -136,10 +124,6 @@ func get_project_health(params: Dictionary) -> Dictionary:
|
|
|
136
124
|
details.append("No project name set")
|
|
137
125
|
deductions += 2
|
|
138
126
|
|
|
139
|
-
if not FileAccess.file_exists("res://export_presets.cfg"):
|
|
140
|
-
details.append("No export presets configured")
|
|
141
|
-
deductions += 3
|
|
142
|
-
|
|
143
127
|
checks["config"] = {"name": "Configuration", "passed": details.is_empty(), "details": details}
|
|
144
128
|
|
|
145
129
|
var score: int = maxi(0, 100 - deductions)
|
|
@@ -156,11 +140,11 @@ func get_project_health(params: Dictionary) -> Dictionary:
|
|
|
156
140
|
else:
|
|
157
141
|
grade = "F"
|
|
158
142
|
|
|
159
|
-
if
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
143
|
+
if score < 70:
|
|
144
|
+
recommendations.append("Address critical issues to improve project stability")
|
|
145
|
+
# A project still being made has no presets yet, which is no fault in it.
|
|
146
|
+
if "config" in check_categories and not FileAccess.file_exists("res://export_presets.cfg"):
|
|
147
|
+
recommendations.append("No export presets are configured: add them before exporting")
|
|
164
148
|
|
|
165
149
|
# Every detail costs points, so each is an issue; `issues` was always empty beside them, and a
|
|
166
150
|
# category said passed next to the failure it had just found.
|
package/build/index.js
CHANGED
|
@@ -3807,6 +3807,18 @@ function prefixIssues(path, issues) {
|
|
|
3807
3807
|
function unwrapMessage(message) {
|
|
3808
3808
|
return typeof message === "string" ? message : message?.message;
|
|
3809
3809
|
}
|
|
3810
|
+
function sizeCaps(defChecks) {
|
|
3811
|
+
const caps = [];
|
|
3812
|
+
for (const ch of defChecks ?? []) {
|
|
3813
|
+
const d = ch._zod.def;
|
|
3814
|
+
if (!/_(length|size)$|_equals$/.test(d.check))
|
|
3815
|
+
break;
|
|
3816
|
+
const max = d.maximum ?? d.length ?? d.size;
|
|
3817
|
+
if (max >= 0)
|
|
3818
|
+
caps.push([max, ch]);
|
|
3819
|
+
}
|
|
3820
|
+
return caps;
|
|
3821
|
+
}
|
|
3810
3822
|
function attachSchema(issues, start, inst) {
|
|
3811
3823
|
var _a;
|
|
3812
3824
|
for (let i = start;i < issues.length; i++) {
|
|
@@ -4808,7 +4820,7 @@ ${content.join(`
|
|
|
4808
4820
|
var version = {
|
|
4809
4821
|
major: 4,
|
|
4810
4822
|
minor: 6,
|
|
4811
|
-
patch:
|
|
4823
|
+
patch: 7
|
|
4812
4824
|
};
|
|
4813
4825
|
|
|
4814
4826
|
// node_modules/zod/v4/core/schemas.js
|
|
@@ -5381,6 +5393,29 @@ var $ZodNever = /* @__PURE__ */ $constructor("$ZodNever", (inst, def) => {
|
|
|
5381
5393
|
return payload;
|
|
5382
5394
|
};
|
|
5383
5395
|
});
|
|
5396
|
+
function capSize(inst, size) {
|
|
5397
|
+
const caps = sizeCaps(inst._zod.def.checks);
|
|
5398
|
+
if (!caps.length)
|
|
5399
|
+
return;
|
|
5400
|
+
const cap = Math.min(...caps.map((c) => c[0]));
|
|
5401
|
+
const parse = inst._zod.parse;
|
|
5402
|
+
inst._zod.parse = (payload, ctx) => {
|
|
5403
|
+
const n = size(payload.value);
|
|
5404
|
+
if (n > cap && !ctx?.skipChecks && ctx?.direction !== "backward") {
|
|
5405
|
+
for (const [max, ch] of sizeCaps(inst._zod.def.checks)) {
|
|
5406
|
+
if (n > max && ch._zod.def.when(payload)) {
|
|
5407
|
+
const start = payload.issues.length;
|
|
5408
|
+
ch._zod.check(payload);
|
|
5409
|
+
payload.issues[start].continue = false;
|
|
5410
|
+
attachSchema(payload.issues, start, inst);
|
|
5411
|
+
return payload;
|
|
5412
|
+
}
|
|
5413
|
+
}
|
|
5414
|
+
}
|
|
5415
|
+
return parse(payload, ctx);
|
|
5416
|
+
};
|
|
5417
|
+
}
|
|
5418
|
+
var arraySize = (input) => Array.isArray(input) ? input.length : -1;
|
|
5384
5419
|
function handleArrayResult(result, final, index) {
|
|
5385
5420
|
if (result.issues.length) {
|
|
5386
5421
|
final.issues.push(...prefixIssues(index, result.issues));
|
|
@@ -5424,6 +5459,7 @@ var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
|
|
|
5424
5459
|
}
|
|
5425
5460
|
return payload;
|
|
5426
5461
|
};
|
|
5462
|
+
capSize(inst, arraySize);
|
|
5427
5463
|
});
|
|
5428
5464
|
function handlePropertyResult(result, final, key, input, optin, optout) {
|
|
5429
5465
|
const isPresent = key in input;
|
|
@@ -31348,7 +31384,11 @@ var PROMPT_SPECS = [
|
|
|
31348
31384
|
}
|
|
31349
31385
|
],
|
|
31350
31386
|
steps: [
|
|
31351
|
-
{
|
|
31387
|
+
{
|
|
31388
|
+
tool: "editor_status",
|
|
31389
|
+
passes: [],
|
|
31390
|
+
why: "see whether an editor is connected and its addon matches; without one the run is a game of its own, not a fault"
|
|
31391
|
+
},
|
|
31352
31392
|
{ tool: "editor_run", op: "start", passes: ["projectPath", "scene"], why: "start the run" },
|
|
31353
31393
|
{
|
|
31354
31394
|
tool: "editor_run",
|
|
@@ -31366,7 +31406,11 @@ var PROMPT_SPECS = [
|
|
|
31366
31406
|
description: "Check the editor connection, the project health report, export validation and the import state.",
|
|
31367
31407
|
arguments: [PROJECT_PATH],
|
|
31368
31408
|
steps: [
|
|
31369
|
-
{
|
|
31409
|
+
{
|
|
31410
|
+
tool: "editor_status",
|
|
31411
|
+
passes: [],
|
|
31412
|
+
why: "see whether an editor is connected and, if one is, whether its addon matches; no editor is no fault in the project, so leave it out of what is wrong"
|
|
31413
|
+
},
|
|
31370
31414
|
{
|
|
31371
31415
|
tool: "project_info",
|
|
31372
31416
|
passes: ["projectPath"],
|
|
@@ -33895,7 +33939,7 @@ var TOOL_SPECS = [
|
|
|
33895
33939
|
{
|
|
33896
33940
|
name: "project_settings",
|
|
33897
33941
|
title: "Project settings",
|
|
33898
|
-
description: "Reads or writes project.godot: settings, autoloads, the main scene, input actions, plugins and audio buses. A write with an editor open on the project is handed to the editor, which takes the settings the write changed or names from the file (named under editorAdopted), including a setting the file already held, since the editor can hold another value after the file was put back, or reloads the bus layout, so it answers the new values and does not save the old ones back over them. editorNote is an editor that could not take the write, one on an addon from before this, which still holds the old values until editor_launch restart. An enabled plugin's code still loads on the editor's next start.",
|
|
33942
|
+
description: "Reads or writes project.godot: settings, autoloads, the main scene, input actions, plugins and audio buses. A write with an editor open on the project is handed to the editor, which takes the settings the write changed or names from the file (named under editorAdopted), including a setting the file already held, since the editor can hold another value after the file was put back, or reloads the bus layout, so it answers the new values and does not save the old ones back over them. editorNote is an editor that could not take the write, one on an addon from before this, which still holds the old values until editor_launch restart. An enabled plugin's code still loads on the editor's next start. set answers old_value and new_value, with was_new true when project.godot did not set the setting before, and was_default true when what it held was the engine's own default, which old_value then is.",
|
|
33899
33943
|
parameters: {
|
|
33900
33944
|
projectPath: PROJECT_PATH2,
|
|
33901
33945
|
setting: { type: "string", description: 'Setting path, such as "display/window/size/viewport_width".' },
|
|
@@ -34598,7 +34642,7 @@ var TOOL_SPECS = [
|
|
|
34598
34642
|
},
|
|
34599
34643
|
check: {
|
|
34600
34644
|
effect: "additive",
|
|
34601
|
-
summary: "boot headless, quit after a few frames, and report the verdict",
|
|
34645
|
+
summary: "boot headless, quit after a few frames, and report the verdict. booted is that verdict rather than whether the game came up: true only for a run that quit on its own within timeoutMs, exited 0 and printed no error, so a game that reached _ready and then raised an error answers false. hung is a run killed at timeoutMs, and errors and warnings count what it printed, which comes back under entries with repeats folded together",
|
|
34602
34646
|
requires: ["projectPath"]
|
|
34603
34647
|
},
|
|
34604
34648
|
wait: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gdharness",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.15",
|
|
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",
|