gdharness 1.2.3 → 1.2.5
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
|
@@ -18898,6 +18898,12 @@ var init_tool_definitions = __esm(() => {
|
|
|
18898
18898
|
ops: ["until"],
|
|
18899
18899
|
description: "until: the value to wait for, fitted to the property's type and compared at the precision the property keeps, so -1.1 meets a 32-bit float holding -1.10000002. A value the property would have to cut is refused: a fraction on a whole number, a number other than 0 or 1 on a bool. On a property holding an object, whether declared to or untyped and holding one or null, the text null means null. One declared to hold an object refuses any value other than null, since it can never hold it."
|
|
18900
18900
|
},
|
|
18901
|
+
compare: {
|
|
18902
|
+
type: "string",
|
|
18903
|
+
enum: ["==", "!=", ">=", "<=", ">", "<"],
|
|
18904
|
+
ops: ["until"],
|
|
18905
|
+
description: "until, with a property: how what the property reads stands to value before the wait is met. Default ==. != waits for it to read as anything else. >=, <=, > and < put a number in order, met on the first look past the value or level with it at the precision the property keeps, which is how a counter that steps rather than lands is waited on: a day counter on a fast clock went from 31 to 34 between two looks, and a wait for 32 ran out. For these the value is the number it is rather than fitted to the property, so a fraction on a whole-number property is a threshold rather than refused, and a property holding anything but a number is refused."
|
|
18906
|
+
},
|
|
18901
18907
|
says: {
|
|
18902
18908
|
type: "string",
|
|
18903
18909
|
ops: ["until"],
|
|
@@ -42117,6 +42123,30 @@ function projectKey(projectPath) {
|
|
|
42117
42123
|
function runRecordPath(projectPath, directory = runtimeDirectory()) {
|
|
42118
42124
|
return join24(directory, "runs", `note-${projectKey(projectPath)}.json`);
|
|
42119
42125
|
}
|
|
42126
|
+
function latestRunPath(servedBy, directory = runtimeDirectory()) {
|
|
42127
|
+
return join24(directory, "runs", `latest-${projectKey(servedBy)}.json`);
|
|
42128
|
+
}
|
|
42129
|
+
function writeLatestRun(servedBy, latest) {
|
|
42130
|
+
try {
|
|
42131
|
+
mkdirSync14(runsDirectory(), { recursive: true });
|
|
42132
|
+
writeFileSync16(latestRunPath(servedBy), JSON.stringify(latest, null, 2), "utf8");
|
|
42133
|
+
} catch {}
|
|
42134
|
+
}
|
|
42135
|
+
function readLatestRun(servedBy, directory = runtimeDirectory()) {
|
|
42136
|
+
try {
|
|
42137
|
+
const fields = JSON.parse(readFileSync21(latestRunPath(servedBy, directory), "utf8"));
|
|
42138
|
+
if (typeof fields !== "object" || fields === null) {
|
|
42139
|
+
return null;
|
|
42140
|
+
}
|
|
42141
|
+
const { projectPath, pid, startedAt } = fields;
|
|
42142
|
+
if (typeof projectPath !== "string" || typeof startedAt !== "number") {
|
|
42143
|
+
return null;
|
|
42144
|
+
}
|
|
42145
|
+
return { projectPath, pid: typeof pid === "number" ? pid : null, startedAt };
|
|
42146
|
+
} catch {
|
|
42147
|
+
return null;
|
|
42148
|
+
}
|
|
42149
|
+
}
|
|
42120
42150
|
function openTranscript(startedAt) {
|
|
42121
42151
|
mkdirSync14(runsDirectory(), { recursive: true });
|
|
42122
42152
|
const path = join24(runsDirectory(), `run-${startedAt}.log`);
|
|
@@ -46563,6 +46593,7 @@ class GodotServer {
|
|
|
46563
46593
|
...which === null ? {} : { play: which }
|
|
46564
46594
|
};
|
|
46565
46595
|
this.activeProcess = played;
|
|
46596
|
+
this.noteTheLatestRun({ projectPath, pid: null, startedAt });
|
|
46566
46597
|
this.watchThePlayedConsole();
|
|
46567
46598
|
writeEditorRunNote({
|
|
46568
46599
|
projectPath,
|
|
@@ -46915,6 +46946,7 @@ class GodotServer {
|
|
|
46915
46946
|
return launched;
|
|
46916
46947
|
}
|
|
46917
46948
|
const startedBy = Date.now();
|
|
46949
|
+
this.noteTheLatestRun({ projectPath, pid: launched.pid, startedAt });
|
|
46918
46950
|
sweepTranscripts();
|
|
46919
46951
|
const noted = readRunRecord(projectPath);
|
|
46920
46952
|
const keeper = noted?.pid === launched.pid ? noted.keeper : undefined;
|
|
@@ -47153,7 +47185,8 @@ class GodotServer {
|
|
|
47153
47185
|
async adoptRecordedRun() {
|
|
47154
47186
|
const project = this.ourProject();
|
|
47155
47187
|
const found = project === null ? [] : [readRunRecord(project), this.startedForUs(project)];
|
|
47156
|
-
const
|
|
47188
|
+
const latest = project === null ? null : readLatestRun(project);
|
|
47189
|
+
const record = latest === null ? found.reduce((newest, one) => one !== null && (newest === null || one.startedAt > newest.startedAt) ? one : newest, null) : found.find((one) => one !== null && one.pid === latest.pid && one.startedAt === latest.startedAt) ?? null;
|
|
47157
47190
|
if (record === null || !(this.couldBeOurs(record.projectPath) || this.couldBeOurs(record.servedBy ?? ""))) {
|
|
47158
47191
|
return null;
|
|
47159
47192
|
}
|
|
@@ -47193,6 +47226,12 @@ class GodotServer {
|
|
|
47193
47226
|
const mine = this.ourProject();
|
|
47194
47227
|
return mine === null ? {} : { servedBy: mine };
|
|
47195
47228
|
}
|
|
47229
|
+
noteTheLatestRun(latest) {
|
|
47230
|
+
const mine = this.ourProject();
|
|
47231
|
+
if (mine !== null) {
|
|
47232
|
+
writeLatestRun(mine, latest);
|
|
47233
|
+
}
|
|
47234
|
+
}
|
|
47196
47235
|
startedForUs(project) {
|
|
47197
47236
|
return everyRunRecord().find((one) => one.servedBy !== undefined && isSameDirectory(one.servedBy, project) && !(one.projectPath !== "" && isSameDirectory(one.projectPath, project))) ?? null;
|
|
47198
47237
|
}
|
|
@@ -48665,6 +48704,7 @@ ${staleNote}`}`
|
|
|
48665
48704
|
path: nodePath,
|
|
48666
48705
|
property: readString(args, "property") ?? "",
|
|
48667
48706
|
value: args["value"],
|
|
48707
|
+
...readString(args, "compare") === undefined ? {} : { compare: readString(args, "compare") },
|
|
48668
48708
|
...readNonEmptyString(args, "says") === undefined ? {} : { says: readNonEmptyString(args, "says") },
|
|
48669
48709
|
...readBoolean(args, "includeHidden") === undefined ? {} : { include_hidden: readBoolean(args, "includeHidden") },
|
|
48670
48710
|
timeout_ms: timeoutMs
|
|
@@ -399,7 +399,7 @@ static func why_hidden(node: Node) -> String:
|
|
|
399
399
|
var control: Control = node as Control
|
|
400
400
|
var instead: Node = null if control == null else drawn_at(control)
|
|
401
401
|
if instead != null:
|
|
402
|
-
return " (%s;
|
|
402
|
+
return " (%s; a click where it would be reaches %s)" % [", and ".join(named), instead.get_path()]
|
|
403
403
|
var outermost: Node = hiding.back()
|
|
404
404
|
var beside: Array[String] = []
|
|
405
405
|
var parent: Node = outermost.get_parent()
|
|
@@ -21,6 +21,11 @@ const MOST_FRAMES: int = 600
|
|
|
21
21
|
## gives looking about a tenth of the time.
|
|
22
22
|
const LOOKS_APART: int = 9
|
|
23
23
|
|
|
24
|
+
## How a property wait compares what it reads with the value: equality by default, and order for a
|
|
25
|
+
## number that steps rather than lands, as a day counter on a fast clock goes from 31 to 34 between
|
|
26
|
+
## two looks and a wait for 32 never sees it.
|
|
27
|
+
const COMPARES: Array[String] = ["==", "!=", ">=", "<=", ">", "<"]
|
|
28
|
+
|
|
24
29
|
var _host: Node
|
|
25
30
|
var _values: Values
|
|
26
31
|
|
|
@@ -107,8 +112,10 @@ func wait_until(params: Dictionary) -> Dictionary:
|
|
|
107
112
|
# path, a property compares one value on one node. Taking says and dropping the other left a
|
|
108
113
|
# caller watching a screen while believing they were watching a property, and the answer says
|
|
109
114
|
# which of them it is about only if you already know that says wins.
|
|
110
|
-
if not says.is_empty() and (not property.is_empty() or params.has("value")):
|
|
111
|
-
var other: String =
|
|
115
|
+
if not says.is_empty() and (not property.is_empty() or params.has("value") or params.has("compare")):
|
|
116
|
+
var other: String = (
|
|
117
|
+
property if not property.is_empty() else ("value" if params.has("value") else "compare")
|
|
118
|
+
)
|
|
112
119
|
return {
|
|
113
120
|
"type": "error",
|
|
114
121
|
"message":
|
|
@@ -123,10 +130,10 @@ func wait_until(params: Dictionary) -> Dictionary:
|
|
|
123
130
|
if not says.is_empty():
|
|
124
131
|
var include_hidden: bool = Read.as_bool(params.get("include_hidden", false))
|
|
125
132
|
return await _wait_until_said(node_path, says, timeout_ms, include_hidden)
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
133
|
+
var unasked: String = _property_wait_unasked(property, params)
|
|
134
|
+
if not unasked.is_empty():
|
|
135
|
+
return {"type": "error", "message": unasked}
|
|
136
|
+
var compare: String = str(params.get("compare", "=="))
|
|
130
137
|
|
|
131
138
|
var node: Node = standing["node"]
|
|
132
139
|
|
|
@@ -139,6 +146,8 @@ func wait_until(params: Dictionary) -> Dictionary:
|
|
|
139
146
|
return watched
|
|
140
147
|
|
|
141
148
|
var current: Variant = watched["value"]
|
|
149
|
+
if compare in [">=", "<=", ">", "<"]:
|
|
150
|
+
return await _wait_in_order(node, params, current, timeout_ms)
|
|
142
151
|
var wanted: Variant = _values.fitted(params["value"], typeof(current))
|
|
143
152
|
# Read against what the property is declared as, not only against what it holds this frame: an
|
|
144
153
|
# object property holding null holds nothing typed, so any value was taken as it came and compared
|
|
@@ -173,9 +182,10 @@ func wait_until(params: Dictionary) -> Dictionary:
|
|
|
173
182
|
# At the precision the property keeps, as set compares: a float arrives as 64 bits and most
|
|
174
183
|
# engine properties keep 32, so h_offset waited on as -1.1 read -1.10000002384186 every frame and
|
|
175
184
|
# the wait ran out on a value the game had reached.
|
|
185
|
+
var differs: bool = compare == "!="
|
|
176
186
|
while (
|
|
177
187
|
Values.comparable(current, wanted)
|
|
178
|
-
and
|
|
188
|
+
and Changes.held_already(wanted, current) == differs
|
|
179
189
|
and Time.get_ticks_msec() - started < timeout_ms
|
|
180
190
|
):
|
|
181
191
|
await _host.get_tree().process_frame
|
|
@@ -191,13 +201,111 @@ func wait_until(params: Dictionary) -> Dictionary:
|
|
|
191
201
|
"type": "condition",
|
|
192
202
|
"path": node_path,
|
|
193
203
|
"property": property,
|
|
194
|
-
"
|
|
204
|
+
"compare": compare,
|
|
205
|
+
"met": Values.comparable(current, wanted) and Changes.held_already(wanted, current) != differs,
|
|
195
206
|
"value": _values.serialize(current),
|
|
196
207
|
"elapsed_ms": Time.get_ticks_msec() - started,
|
|
197
208
|
"frames": frames,
|
|
198
209
|
}
|
|
199
210
|
|
|
200
211
|
|
|
212
|
+
## What a property wait is missing or was given wrongly, or "" when it can go ahead.
|
|
213
|
+
static func _property_wait_unasked(property: String, params: Dictionary) -> String:
|
|
214
|
+
if property.is_empty():
|
|
215
|
+
return "A property and a value, or says, are required"
|
|
216
|
+
if not params.has("value"):
|
|
217
|
+
return "A value to wait for is required"
|
|
218
|
+
var compare: String = str(params.get("compare", "=="))
|
|
219
|
+
if not COMPARES.has(compare):
|
|
220
|
+
return 'compare is one of %s, not "%s"' % [", ".join(COMPARES), compare]
|
|
221
|
+
return ""
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
## [method wait_until] for a number compared by order: met on the first look at which the property
|
|
225
|
+
## is past the value, or level with it at the precision the property keeps, as `==` compares.
|
|
226
|
+
##
|
|
227
|
+
## The value is read as the number it is rather than fitted to the property's type, since fitting
|
|
228
|
+
## truncates: 31.5 on a whole-number property became 31, and a wait for "at least 31.5" was met at 31.
|
|
229
|
+
func _wait_in_order(node: Node, params: Dictionary, current: Variant, timeout_ms: int) -> Dictionary:
|
|
230
|
+
var node_path: String = str(params.get("path", ""))
|
|
231
|
+
var property: String = str(params.get("property", ""))
|
|
232
|
+
var compare: String = str(params.get("compare", ""))
|
|
233
|
+
var given: Variant = params["value"]
|
|
234
|
+
# The property first: a string waited on in order is refused for being a string, whatever value
|
|
235
|
+
# came with it, since no number would make the wait answerable.
|
|
236
|
+
var unordered: String = _no_order(current, node_path, property, compare)
|
|
237
|
+
if not unordered.is_empty():
|
|
238
|
+
return {"type": "error", "message": unordered}
|
|
239
|
+
var number: Variant = given
|
|
240
|
+
if given is String:
|
|
241
|
+
var text: String = given
|
|
242
|
+
number = Read.json_or_null(text)
|
|
243
|
+
if typeof(number) != TYPE_INT and typeof(number) != TYPE_FLOAT:
|
|
244
|
+
return {
|
|
245
|
+
"type": "error",
|
|
246
|
+
"message":
|
|
247
|
+
(
|
|
248
|
+
"compare %s puts a number in order, and the value to wait for is %s: give a number."
|
|
249
|
+
% [compare, str(given)]
|
|
250
|
+
)
|
|
251
|
+
}
|
|
252
|
+
var limit: float = Read.as_float(number)
|
|
253
|
+
|
|
254
|
+
var started: int = Time.get_ticks_msec()
|
|
255
|
+
var frames: int = 0
|
|
256
|
+
while not _in_order(compare, limit, current) and Time.get_ticks_msec() - started < timeout_ms:
|
|
257
|
+
await _host.get_tree().process_frame
|
|
258
|
+
frames += 1
|
|
259
|
+
if not is_instance_valid(node):
|
|
260
|
+
return {"type": "error", "message": "%s was freed while waiting" % node_path}
|
|
261
|
+
var watched: Dictionary = _watched(node, node_path, property)
|
|
262
|
+
if watched.has("message"):
|
|
263
|
+
return watched
|
|
264
|
+
current = watched["value"]
|
|
265
|
+
unordered = _no_order(current, node_path, property, compare)
|
|
266
|
+
if not unordered.is_empty():
|
|
267
|
+
return {"type": "error", "message": unordered}
|
|
268
|
+
|
|
269
|
+
return {
|
|
270
|
+
"type": "condition",
|
|
271
|
+
"path": node_path,
|
|
272
|
+
"property": property,
|
|
273
|
+
"compare": compare,
|
|
274
|
+
"met": _in_order(compare, limit, current),
|
|
275
|
+
"value": _values.serialize(current),
|
|
276
|
+
"elapsed_ms": Time.get_ticks_msec() - started,
|
|
277
|
+
"frames": frames,
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
## Why [param current] cannot be put in order, or "" when it is a number.
|
|
282
|
+
static func _no_order(current: Variant, node_path: String, property: String, compare: String) -> String:
|
|
283
|
+
if typeof(current) == TYPE_INT or typeof(current) == TYPE_FLOAT:
|
|
284
|
+
return ""
|
|
285
|
+
return (
|
|
286
|
+
"%s.%s holds %s, which has no order, so compare %s cannot be asked of it: use == or !=."
|
|
287
|
+
% [node_path, property, type_string(typeof(current)), compare]
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
## Whether [param current], a number, stands to [param limit] as [param compare] says. Level counts
|
|
292
|
+
## at the precision the property keeps, so a 32-bit float holding 0.30000001 is at least 0.3.
|
|
293
|
+
static func _in_order(compare: String, limit: float, current: Variant) -> bool:
|
|
294
|
+
var reading: float = Read.as_float(current)
|
|
295
|
+
var level: bool = (
|
|
296
|
+
reading == limit or (typeof(current) == TYPE_FLOAT and Changes.held_already(limit, current))
|
|
297
|
+
)
|
|
298
|
+
match compare:
|
|
299
|
+
">=":
|
|
300
|
+
return level or reading > limit
|
|
301
|
+
"<=":
|
|
302
|
+
return level or reading < limit
|
|
303
|
+
">":
|
|
304
|
+
return not level and reading > limit
|
|
305
|
+
_:
|
|
306
|
+
return not level and reading < limit
|
|
307
|
+
|
|
308
|
+
|
|
201
309
|
## Why [param given] would have to be cut to be waited on a whole number or a truth, or "" when not.
|
|
202
310
|
##
|
|
203
311
|
## A number arrives from JSON as a float, so one is converted to what the property holds, and the
|
package/build/index.js
CHANGED
|
@@ -32922,6 +32922,30 @@ function projectKey(projectPath) {
|
|
|
32922
32922
|
function runRecordPath(projectPath, directory = runtimeDirectory()) {
|
|
32923
32923
|
return join19(directory, "runs", `note-${projectKey(projectPath)}.json`);
|
|
32924
32924
|
}
|
|
32925
|
+
function latestRunPath(servedBy, directory = runtimeDirectory()) {
|
|
32926
|
+
return join19(directory, "runs", `latest-${projectKey(servedBy)}.json`);
|
|
32927
|
+
}
|
|
32928
|
+
function writeLatestRun(servedBy, latest) {
|
|
32929
|
+
try {
|
|
32930
|
+
mkdirSync11(runsDirectory(), { recursive: true });
|
|
32931
|
+
writeFileSync13(latestRunPath(servedBy), JSON.stringify(latest, null, 2), "utf8");
|
|
32932
|
+
} catch {}
|
|
32933
|
+
}
|
|
32934
|
+
function readLatestRun(servedBy, directory = runtimeDirectory()) {
|
|
32935
|
+
try {
|
|
32936
|
+
const fields = JSON.parse(readFileSync18(latestRunPath(servedBy, directory), "utf8"));
|
|
32937
|
+
if (typeof fields !== "object" || fields === null) {
|
|
32938
|
+
return null;
|
|
32939
|
+
}
|
|
32940
|
+
const { projectPath, pid, startedAt } = fields;
|
|
32941
|
+
if (typeof projectPath !== "string" || typeof startedAt !== "number") {
|
|
32942
|
+
return null;
|
|
32943
|
+
}
|
|
32944
|
+
return { projectPath, pid: typeof pid === "number" ? pid : null, startedAt };
|
|
32945
|
+
} catch {
|
|
32946
|
+
return null;
|
|
32947
|
+
}
|
|
32948
|
+
}
|
|
32925
32949
|
var SHARED_NOTE = "run.json";
|
|
32926
32950
|
function openTranscript(startedAt) {
|
|
32927
32951
|
mkdirSync11(runsDirectory(), { recursive: true });
|
|
@@ -35001,6 +35025,12 @@ var TOOL_SPECS = [
|
|
|
35001
35025
|
ops: ["until"],
|
|
35002
35026
|
description: "until: the value to wait for, fitted to the property's type and compared at the precision the property keeps, so -1.1 meets a 32-bit float holding -1.10000002. A value the property would have to cut is refused: a fraction on a whole number, a number other than 0 or 1 on a bool. On a property holding an object, whether declared to or untyped and holding one or null, the text null means null. One declared to hold an object refuses any value other than null, since it can never hold it."
|
|
35003
35027
|
},
|
|
35028
|
+
compare: {
|
|
35029
|
+
type: "string",
|
|
35030
|
+
enum: ["==", "!=", ">=", "<=", ">", "<"],
|
|
35031
|
+
ops: ["until"],
|
|
35032
|
+
description: "until, with a property: how what the property reads stands to value before the wait is met. Default ==. != waits for it to read as anything else. >=, <=, > and < put a number in order, met on the first look past the value or level with it at the precision the property keeps, which is how a counter that steps rather than lands is waited on: a day counter on a fast clock went from 31 to 34 between two looks, and a wait for 32 ran out. For these the value is the number it is rather than fitted to the property, so a fraction on a whole-number property is a threshold rather than refused, and a property holding anything but a number is refused."
|
|
35033
|
+
},
|
|
35004
35034
|
says: {
|
|
35005
35035
|
type: "string",
|
|
35006
35036
|
ops: ["until"],
|
|
@@ -39060,6 +39090,7 @@ class GodotServer {
|
|
|
39060
39090
|
...which === null ? {} : { play: which }
|
|
39061
39091
|
};
|
|
39062
39092
|
this.activeProcess = played;
|
|
39093
|
+
this.noteTheLatestRun({ projectPath, pid: null, startedAt });
|
|
39063
39094
|
this.watchThePlayedConsole();
|
|
39064
39095
|
writeEditorRunNote({
|
|
39065
39096
|
projectPath,
|
|
@@ -39412,6 +39443,7 @@ class GodotServer {
|
|
|
39412
39443
|
return launched;
|
|
39413
39444
|
}
|
|
39414
39445
|
const startedBy = Date.now();
|
|
39446
|
+
this.noteTheLatestRun({ projectPath, pid: launched.pid, startedAt });
|
|
39415
39447
|
sweepTranscripts();
|
|
39416
39448
|
const noted = readRunRecord(projectPath);
|
|
39417
39449
|
const keeper = noted?.pid === launched.pid ? noted.keeper : undefined;
|
|
@@ -39650,7 +39682,8 @@ class GodotServer {
|
|
|
39650
39682
|
async adoptRecordedRun() {
|
|
39651
39683
|
const project = this.ourProject();
|
|
39652
39684
|
const found = project === null ? [] : [readRunRecord(project), this.startedForUs(project)];
|
|
39653
|
-
const
|
|
39685
|
+
const latest = project === null ? null : readLatestRun(project);
|
|
39686
|
+
const record = latest === null ? found.reduce((newest, one) => one !== null && (newest === null || one.startedAt > newest.startedAt) ? one : newest, null) : found.find((one) => one !== null && one.pid === latest.pid && one.startedAt === latest.startedAt) ?? null;
|
|
39654
39687
|
if (record === null || !(this.couldBeOurs(record.projectPath) || this.couldBeOurs(record.servedBy ?? ""))) {
|
|
39655
39688
|
return null;
|
|
39656
39689
|
}
|
|
@@ -39690,6 +39723,12 @@ class GodotServer {
|
|
|
39690
39723
|
const mine = this.ourProject();
|
|
39691
39724
|
return mine === null ? {} : { servedBy: mine };
|
|
39692
39725
|
}
|
|
39726
|
+
noteTheLatestRun(latest) {
|
|
39727
|
+
const mine = this.ourProject();
|
|
39728
|
+
if (mine !== null) {
|
|
39729
|
+
writeLatestRun(mine, latest);
|
|
39730
|
+
}
|
|
39731
|
+
}
|
|
39693
39732
|
startedForUs(project) {
|
|
39694
39733
|
return everyRunRecord().find((one) => one.servedBy !== undefined && isSameDirectory(one.servedBy, project) && !(one.projectPath !== "" && isSameDirectory(one.projectPath, project))) ?? null;
|
|
39695
39734
|
}
|
|
@@ -41162,6 +41201,7 @@ ${staleNote}`}`
|
|
|
41162
41201
|
path: nodePath,
|
|
41163
41202
|
property: readString(args, "property") ?? "",
|
|
41164
41203
|
value: args["value"],
|
|
41204
|
+
...readString(args, "compare") === undefined ? {} : { compare: readString(args, "compare") },
|
|
41165
41205
|
...readNonEmptyString(args, "says") === undefined ? {} : { says: readNonEmptyString(args, "says") },
|
|
41166
41206
|
...readBoolean(args, "includeHidden") === undefined ? {} : { include_hidden: readBoolean(args, "includeHidden") },
|
|
41167
41207
|
timeout_ms: timeoutMs
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gdharness",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
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",
|