@skillcap/gdh 3.1.0 → 3.2.0

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.
Files changed (31) hide show
  1. package/INSTALL-BUNDLE.json +1 -1
  2. package/RELEASE-SPAN-UPDATE-CONTRACTS.json +83 -0
  3. package/node_modules/@gdh/adapters/package.json +8 -8
  4. package/node_modules/@gdh/authoring/package.json +2 -2
  5. package/node_modules/@gdh/cli/dist/index.js.map +1 -1
  6. package/node_modules/@gdh/cli/package.json +11 -11
  7. package/node_modules/@gdh/core/dist/index.d.ts +5 -5
  8. package/node_modules/@gdh/core/dist/index.d.ts.map +1 -1
  9. package/node_modules/@gdh/core/dist/index.js +4 -4
  10. package/node_modules/@gdh/core/dist/index.js.map +1 -1
  11. package/node_modules/@gdh/core/package.json +1 -1
  12. package/node_modules/@gdh/docs/dist/guidance.d.ts.map +1 -1
  13. package/node_modules/@gdh/docs/dist/guidance.js +29 -0
  14. package/node_modules/@gdh/docs/dist/guidance.js.map +1 -1
  15. package/node_modules/@gdh/docs/dist/templates/guidance/editor-bridge.md.tpl +28 -0
  16. package/node_modules/@gdh/docs/package.json +2 -2
  17. package/node_modules/@gdh/editor/dist/index.d.ts +24 -3
  18. package/node_modules/@gdh/editor/dist/index.d.ts.map +1 -1
  19. package/node_modules/@gdh/editor/dist/index.js +323 -7
  20. package/node_modules/@gdh/editor/dist/index.js.map +1 -1
  21. package/node_modules/@gdh/editor/package.json +2 -2
  22. package/node_modules/@gdh/mcp/dist/index.d.ts.map +1 -1
  23. package/node_modules/@gdh/mcp/dist/index.js +290 -2
  24. package/node_modules/@gdh/mcp/dist/index.js.map +1 -1
  25. package/node_modules/@gdh/mcp/package.json +10 -10
  26. package/node_modules/@gdh/observability/package.json +2 -2
  27. package/node_modules/@gdh/runtime/dist/bridge-surface.js +1 -1
  28. package/node_modules/@gdh/runtime/package.json +3 -3
  29. package/node_modules/@gdh/scan/package.json +3 -3
  30. package/node_modules/@gdh/verify/package.json +7 -7
  31. package/package.json +12 -12
@@ -0,0 +1,28 @@
1
+ # {{projectName}}: Editor Bridge
2
+
3
+ Use this unit when the task asks about the Godot editor, the currently open scene, scene tree inspection, node inspection, resource properties, or editor-backed scene/resource authoring.
4
+
5
+ Start with context before guessing:
6
+
7
+ - Use MCP `editor.state` to inspect the exact target/worktree editor session. In adopted-editor mode it reports current/open scene and selected nodes when the editor exposes them.
8
+ - Use MCP `editor.scene.tree` for a saved scene tree. It requires an explicit `scenePath`; if you need the active editor scene first, call `editor.state`.
9
+ - Use MCP `editor.node.inspect` for inspector-style node context from a saved scene: node summary plus requested property values or a bounded property list.
10
+ - Use MCP `editor.resource.properties` before `editor.resource.read` when you do not already know the resource property names.
11
+ - Use MCP `editor.resource.read` for targeted resource values. Nested arrays and dictionaries are bounded and resources are returned as handles when Godot exposes a resource path.
12
+ - Use MCP `editor.class.search` and `editor.class.info` for class discovery instead of guessing Godot class names or property names.
13
+
14
+ Use `editor.operation.run` only as the advanced escape hatch for operation kinds not covered by a focused MCP tool or for batched editor operations. Generic operation payloads dispatch on `operation.kind`, not `operation.type`.
15
+
16
+ Recover from bad editor-operation payloads by reading the returned `summary`, `reasons`, and `help.examples`. CLI smoke-test help is available with:
17
+
18
+ ```sh
19
+ gdh editor operation run --help
20
+ ```
21
+
22
+ Do not read `.godot/` cache files to answer live editor-state questions while GDH editor tools are available. `.godot/` remains generated editor/import state; use it only when GDH explicitly reports that editor context is unavailable and you surface that limitation.
23
+
24
+ Boundaries:
25
+
26
+ - Current editor context and selection are available only from adopted editor sessions that expose editor APIs. Managed headless editor operations can load saved scenes/resources, but they do not have a human editor selection.
27
+ - Scene/resource reads are bounded inspection and authoring support, not UI automation of the Godot editor.
28
+ - Arbitrary editor script execution, broad editor UI automation, animation editor operations, TileMap/TileSet editing, and generic file maintenance remain outside this guidance.
@@ -11,8 +11,8 @@
11
11
  }
12
12
  },
13
13
  "dependencies": {
14
- "@gdh/core": "3.1.0",
14
+ "@gdh/core": "3.2.0",
15
15
  "yaml": "^2.8.3"
16
16
  },
17
- "version": "3.1.0"
17
+ "version": "3.2.0"
18
18
  }
@@ -105,6 +105,14 @@ export type GdhEditorOperation = {
105
105
  readonly scenePath: string;
106
106
  readonly nodePath: string;
107
107
  readonly propertyName: string;
108
+ } | {
109
+ readonly kind: "node.inspect";
110
+ readonly scenePath: string;
111
+ readonly nodePath?: string;
112
+ readonly propertyNames?: readonly string[];
113
+ readonly includePropertyList?: boolean;
114
+ readonly propertyQuery?: string;
115
+ readonly propertyLimit?: number;
108
116
  } | {
109
117
  readonly kind: "resource.create";
110
118
  readonly resourcePath: string;
@@ -114,6 +122,11 @@ export type GdhEditorOperation = {
114
122
  readonly kind: "resource.read";
115
123
  readonly resourcePath: string;
116
124
  readonly propertyNames?: readonly string[];
125
+ } | {
126
+ readonly kind: "resource.properties";
127
+ readonly resourcePath: string;
128
+ readonly propertyQuery?: string;
129
+ readonly propertyLimit?: number;
117
130
  } | {
118
131
  readonly kind: "resource.set_property";
119
132
  readonly resourcePath: string;
@@ -142,14 +155,21 @@ export type GdhEditorOperation = {
142
155
  readonly kind: "batch.apply";
143
156
  readonly operations: readonly GdhEditorOperation[];
144
157
  };
158
+ export type GdhEditorOperationPayload = Readonly<Record<string, GdhJsonValue>>;
159
+ export interface GdhEditorOperationHelp {
160
+ readonly usage: string;
161
+ readonly helpCommand: string;
162
+ readonly examples: readonly Readonly<Record<string, GdhJsonValue>>[];
163
+ }
145
164
  export interface GdhEditorOperationResult {
146
165
  readonly targetPath: string;
147
166
  readonly state: GdhEditorOperationState;
148
167
  readonly summary: string;
149
168
  readonly reasons: readonly string[];
150
169
  readonly session: GdhEditorSessionSummary;
151
- readonly operation: GdhEditorOperation;
170
+ readonly operation: GdhEditorOperationPayload;
152
171
  readonly output: GdhJsonValue;
172
+ readonly help?: GdhEditorOperationHelp | null;
153
173
  readonly artifacts: {
154
174
  readonly operationId: string;
155
175
  readonly directory: string;
@@ -161,7 +181,7 @@ export interface GdhEditorOperationResult {
161
181
  } | null;
162
182
  }
163
183
  export interface RunEditorOperationInput extends ResolveEditorBridgePathsInput {
164
- readonly operation: GdhEditorOperation;
184
+ readonly operation: GdhEditorOperationPayload;
165
185
  readonly mode?: GdhEditorSessionMode;
166
186
  readonly timeoutMs?: number;
167
187
  readonly godotEditorBin?: string | null;
@@ -186,7 +206,7 @@ export type InvokeAdoptedEditor = (input: {
186
206
  readonly metadata: GdhEditorAdoptionMetadata;
187
207
  readonly token: string;
188
208
  readonly identity: GdhBridgeTargetIdentity;
189
- readonly operation: GdhEditorOperation;
209
+ readonly operation: GdhEditorOperationPayload;
190
210
  readonly timeoutMs: number;
191
211
  }) => Promise<RunnerOutput>;
192
212
  export interface GdhEditorRunnerOutput {
@@ -194,6 +214,7 @@ export interface GdhEditorRunnerOutput {
194
214
  readonly summary?: string;
195
215
  readonly reasons?: readonly string[];
196
216
  readonly output?: GdhJsonValue;
217
+ readonly help?: GdhEditorOperationHelp | null;
197
218
  }
198
219
  type RunnerOutput = GdhEditorRunnerOutput;
199
220
  export declare function resolveEditorBridgePaths(input: ResolveEditorBridgePathsInput): GdhEditorBridgePaths;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -117,8 +117,187 @@ export async function inspectEditorBridgeSession(input) {
117
117
  adoptedEditor: null,
118
118
  };
119
119
  }
120
+ function validateEditorOperation(operation) {
121
+ const kind = readPayloadString(operation["kind"]);
122
+ const help = createEditorOperationHelp(kind);
123
+ if (kind === "") {
124
+ const typeValue = readPayloadString(operation["type"]);
125
+ const operationHelp = typeValue === "" ? help : createEditorOperationHelp(typeValue);
126
+ return {
127
+ summary: typeValue === ""
128
+ ? `Editor operation payload is missing "kind". Use operation.kind, for example ${JSON.stringify(help.examples[0])}.`
129
+ : `Editor operation payload used "type": "${typeValue}", but GDH dispatches editor operations with "kind". Use ${JSON.stringify(operationHelp.examples[0])}.`,
130
+ reasons: typeValue === ""
131
+ ? ["operation_kind_missing"]
132
+ : ["operation_kind_missing", "operation_type_unsupported"],
133
+ help: operationHelp,
134
+ };
135
+ }
136
+ if (!KNOWN_EDITOR_OPERATION_KINDS.has(kind)) {
137
+ return {
138
+ summary: `Unsupported editor operation kind "${kind}". Use one of: ${[
139
+ ...KNOWN_EDITOR_OPERATION_KINDS,
140
+ ].join(", ")}.`,
141
+ reasons: ["operation_unsupported"],
142
+ help,
143
+ };
144
+ }
145
+ const missingField = requiredFieldForOperation(kind, operation);
146
+ if (missingField !== null) {
147
+ return {
148
+ summary: `Editor operation "${kind}" requires "${missingField}". Example: ${JSON.stringify(createEditorOperationHelp(kind).examples[0])}.`,
149
+ reasons: [`${toSnakeCase(missingField)}_missing`],
150
+ help: createEditorOperationHelp(kind),
151
+ };
152
+ }
153
+ if (kind === "batch.apply") {
154
+ const operations = operation["operations"];
155
+ if (!Array.isArray(operations)) {
156
+ return {
157
+ summary: 'Editor operation "batch.apply" requires "operations" as an array of operation payloads.',
158
+ reasons: ["batch_operations_invalid"],
159
+ help,
160
+ };
161
+ }
162
+ for (const child of operations) {
163
+ if (child === null || Array.isArray(child) || typeof child !== "object") {
164
+ return {
165
+ summary: 'Editor operation "batch.apply" children must be operation objects.',
166
+ reasons: ["batch_child_operation_invalid"],
167
+ help,
168
+ };
169
+ }
170
+ const childValidation = validateEditorOperation(child);
171
+ if (childValidation !== null)
172
+ return childValidation;
173
+ }
174
+ }
175
+ return null;
176
+ }
177
+ const KNOWN_EDITOR_OPERATION_KINDS = new Set([
178
+ "scene.create",
179
+ "scene.tree",
180
+ "scene.save",
181
+ "node.add",
182
+ "node.remove",
183
+ "node.reparent",
184
+ "node.duplicate",
185
+ "node.set_property",
186
+ "node.get_property",
187
+ "node.inspect",
188
+ "resource.create",
189
+ "resource.read",
190
+ "resource.properties",
191
+ "resource.set_property",
192
+ "script.attach",
193
+ "class.search",
194
+ "class.info",
195
+ "editor.state",
196
+ "batch.apply",
197
+ ]);
198
+ function requiredFieldForOperation(kind, operation) {
199
+ const require = (...fields) => fields.find((field) => readPayloadString(operation[field]) === "") ?? null;
200
+ switch (kind) {
201
+ case "scene.create":
202
+ case "scene.tree":
203
+ case "scene.save":
204
+ return require("scenePath");
205
+ case "node.add":
206
+ return require("scenePath", "nodeType", "nodeName");
207
+ case "node.remove":
208
+ case "node.reparent":
209
+ case "node.duplicate":
210
+ return require("scenePath", "nodePath");
211
+ case "node.set_property":
212
+ case "node.get_property":
213
+ return require("scenePath", "nodePath", "propertyName");
214
+ case "node.inspect":
215
+ return require("scenePath");
216
+ case "resource.create":
217
+ return require("resourcePath", "resourceType");
218
+ case "resource.read":
219
+ case "resource.properties":
220
+ return require("resourcePath");
221
+ case "resource.set_property":
222
+ return require("resourcePath", "propertyName");
223
+ case "script.attach":
224
+ return require("scenePath", "nodePath", "scriptPath");
225
+ case "class.info":
226
+ return require("className");
227
+ default:
228
+ return null;
229
+ }
230
+ }
231
+ function createEditorOperationHelp(kind) {
232
+ const example = editorOperationExample(kind);
233
+ return {
234
+ usage: "Use editor.operation.run with an operation object that contains a kind field, or prefer focused MCP tools such as editor.state, editor.scene.tree, editor.resource.read, editor.resource.properties, editor.node.inspect, editor.class.search, and editor.class.info.",
235
+ helpCommand: 'gdh editor operation run --help; example: gdh editor operation run --input-json \'{"kind":"class.search","query":"Label"}\'',
236
+ examples: [example],
237
+ };
238
+ }
239
+ function editorOperationExample(kind) {
240
+ switch (kind) {
241
+ case "scene.tree":
242
+ return { kind: "scene.tree", scenePath: "res://path/to/scene.tscn", maxDepth: 3 };
243
+ case "node.inspect":
244
+ return {
245
+ kind: "node.inspect",
246
+ scenePath: "res://path/to/scene.tscn",
247
+ nodePath: ".",
248
+ includePropertyList: true,
249
+ propertyLimit: 40,
250
+ };
251
+ case "resource.read":
252
+ return {
253
+ kind: "resource.read",
254
+ resourcePath: "res://path/to/resource.tres",
255
+ propertyNames: ["name"],
256
+ };
257
+ case "resource.properties":
258
+ return { kind: "resource.properties", resourcePath: "res://path/to/resource.tres" };
259
+ case "class.search":
260
+ return { kind: "class.search", query: "Label" };
261
+ case "class.info":
262
+ return { kind: "class.info", className: "Label", propertyQuery: "text" };
263
+ case "editor.state":
264
+ return { kind: "editor.state" };
265
+ default:
266
+ return { kind: "editor.state" };
267
+ }
268
+ }
269
+ function readPayloadString(value) {
270
+ return typeof value === "string" ? value : "";
271
+ }
272
+ function toSnakeCase(value) {
273
+ return value.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
274
+ }
120
275
  export async function runEditorOperation(input) {
121
276
  const paths = resolveEditorBridgePaths(input);
277
+ const operationValidation = validateEditorOperation(input.operation);
278
+ if (operationValidation !== null) {
279
+ return {
280
+ targetPath: paths.targetRootPath,
281
+ state: "failed",
282
+ summary: operationValidation.summary,
283
+ reasons: operationValidation.reasons,
284
+ session: {
285
+ targetPath: paths.targetRootPath,
286
+ godotProjectRootPath: paths.godotProjectRootPath,
287
+ mode: input.mode ?? "auto",
288
+ state: "blocked",
289
+ kind: null,
290
+ summary: "Editor operation was rejected before session startup.",
291
+ reasons: operationValidation.reasons,
292
+ identity: paths.identity,
293
+ adoptedEditor: null,
294
+ },
295
+ operation: input.operation,
296
+ output: null,
297
+ help: operationValidation.help,
298
+ artifacts: null,
299
+ };
300
+ }
122
301
  const session = await inspectEditorBridgeSession(input);
123
302
  if (session.state !== "ready" || session.kind === null) {
124
303
  return {
@@ -129,6 +308,7 @@ export async function runEditorOperation(input) {
129
308
  session,
130
309
  operation: input.operation,
131
310
  output: null,
311
+ help: null,
132
312
  artifacts: null,
133
313
  };
134
314
  }
@@ -145,6 +325,7 @@ export async function runEditorOperation(input) {
145
325
  session,
146
326
  operation: input.operation,
147
327
  output: null,
328
+ help: null,
148
329
  artifacts: null,
149
330
  };
150
331
  }
@@ -198,6 +379,7 @@ export async function runEditorOperation(input) {
198
379
  session,
199
380
  operation: input.operation,
200
381
  output: null,
382
+ help: null,
201
383
  artifacts,
202
384
  };
203
385
  }
@@ -210,6 +392,7 @@ export async function runEditorOperation(input) {
210
392
  session,
211
393
  operation: input.operation,
212
394
  output: runnerOutput.output ?? null,
395
+ help: runnerOutput.help ?? null,
213
396
  artifacts,
214
397
  };
215
398
  }
@@ -224,6 +407,7 @@ async function runAdoptedEditorOperation(input) {
224
407
  session: input.session,
225
408
  operation: input.input.operation,
226
409
  output: null,
410
+ help: null,
227
411
  artifacts: null,
228
412
  };
229
413
  }
@@ -259,6 +443,7 @@ async function runAdoptedEditorOperation(input) {
259
443
  session: input.session,
260
444
  operation: input.input.operation,
261
445
  output: runnerOutput.output ?? null,
446
+ help: runnerOutput.help ?? null,
262
447
  artifacts,
263
448
  };
264
449
  }
@@ -537,6 +722,11 @@ func run_editor_operation(operation: Dictionary) -> Dictionary:
537
722
 
538
723
  func _dispatch_operation(operation: Dictionary) -> Dictionary:
539
724
  var kind := str(operation.get("kind", ""))
725
+ if kind == "":
726
+ var type_value := str(operation.get("type", ""))
727
+ if type_value != "":
728
+ return _failure("Editor operation payload used type='" + type_value + "', but GDH dispatches editor operations with kind. Use operation.kind instead.", ["operation_kind_missing", "operation_type_unsupported"], _operation_help(type_value))
729
+ return _failure("Editor operation payload is missing kind.", ["operation_kind_missing"], _operation_help("editor.state"))
540
730
  match kind:
541
731
  "scene.create":
542
732
  return _scene_create(operation)
@@ -556,10 +746,14 @@ func _dispatch_operation(operation: Dictionary) -> Dictionary:
556
746
  return _node_set_property(operation)
557
747
  "node.get_property":
558
748
  return _node_get_property(operation)
749
+ "node.inspect":
750
+ return _node_inspect(operation)
559
751
  "resource.create":
560
752
  return _resource_create(operation)
561
753
  "resource.read":
562
754
  return _resource_read(operation)
755
+ "resource.properties":
756
+ return _resource_properties(operation)
563
757
  "resource.set_property":
564
758
  return _resource_set_property(operation)
565
759
  "script.attach":
@@ -573,7 +767,7 @@ func _dispatch_operation(operation: Dictionary) -> Dictionary:
573
767
  "batch.apply":
574
768
  return _batch_apply(operation)
575
769
  _:
576
- return _failure("Unsupported editor operation: " + kind, ["operation_unsupported"])
770
+ return _failure("Unsupported editor operation: " + kind, ["operation_unsupported"], _operation_help(kind))
577
771
 
578
772
  func _scene_create(operation: Dictionary) -> Dictionary:
579
773
  var scene_path := _res_path(str(operation.get("scenePath", "")))
@@ -597,6 +791,8 @@ func _scene_create(operation: Dictionary) -> Dictionary:
597
791
 
598
792
  func _scene_tree(operation: Dictionary) -> Dictionary:
599
793
  var scene_path := _res_path(str(operation.get("scenePath", "")))
794
+ if scene_path == "res://":
795
+ return _failure("scene.tree requires scenePath.", ["scene_path_missing"], _operation_help("scene.tree"))
600
796
  var loaded = load(scene_path)
601
797
  if loaded == null or not (loaded is PackedScene):
602
798
  return _failure("Scene could not be loaded: " + scene_path, ["scene_load_failed"])
@@ -739,6 +935,31 @@ func _node_get_property(operation: Dictionary) -> Dictionary:
739
935
  root.queue_free()
740
936
  return _success("Node property read.", {"scenePath": scene_path, "nodePath": node_path, "propertyName": property_name, "value": value})
741
937
 
938
+ func _node_inspect(operation: Dictionary) -> Dictionary:
939
+ var scene_path := _res_path(str(operation.get("scenePath", "")))
940
+ if scene_path == "res://":
941
+ return _failure("node.inspect requires scenePath.", ["scene_path_missing"], _operation_help("node.inspect"))
942
+ var root = _load_scene_root(scene_path)
943
+ if root == null:
944
+ return _failure("Scene could not be loaded: " + scene_path, ["scene_load_failed"])
945
+ var node_path := str(operation.get("nodePath", "."))
946
+ var node = _find_node(root, node_path)
947
+ if node == null:
948
+ root.queue_free()
949
+ return _failure("Node not found: " + node_path, ["node_not_found"])
950
+ var property_names = operation.get("propertyNames", [])
951
+ var properties := {}
952
+ if typeof(property_names) == TYPE_ARRAY:
953
+ for property_name in property_names:
954
+ var key := str(property_name)
955
+ properties[key] = _encode_value(node.get(key))
956
+ var property_list := []
957
+ if bool(operation.get("includePropertyList", false)):
958
+ property_list = _filter_property_list(node.get_property_list(), str(operation.get("propertyQuery", "")), int(operation.get("propertyLimit", 50)))
959
+ var summary := _node_summary(node, node_path, 0, 0)
960
+ root.queue_free()
961
+ return _success("Node inspected.", {"scenePath": scene_path, "nodePath": node_path, "node": summary, "properties": properties, "propertyList": property_list})
962
+
742
963
  func _resource_create(operation: Dictionary) -> Dictionary:
743
964
  var resource_path := _res_path(str(operation.get("resourcePath", "")))
744
965
  var resource_type := str(operation.get("resourceType", ""))
@@ -754,6 +975,8 @@ func _resource_create(operation: Dictionary) -> Dictionary:
754
975
 
755
976
  func _resource_read(operation: Dictionary) -> Dictionary:
756
977
  var resource_path := _res_path(str(operation.get("resourcePath", "")))
978
+ if resource_path == "res://":
979
+ return _failure("resource.read requires resourcePath.", ["resource_path_missing"], _operation_help("resource.read"))
757
980
  var resource = load(resource_path)
758
981
  if resource == null or not (resource is Resource):
759
982
  return _failure("Resource could not be loaded: " + resource_path, ["resource_load_failed"])
@@ -766,6 +989,17 @@ func _resource_read(operation: Dictionary) -> Dictionary:
766
989
  var script = resource.get_script()
767
990
  return _success("Resource read.", {"resourcePath": resource_path, "class": resource.get_class(), "scriptPath": script.resource_path if script else null, "properties": properties})
768
991
 
992
+ func _resource_properties(operation: Dictionary) -> Dictionary:
993
+ var resource_path := _res_path(str(operation.get("resourcePath", "")))
994
+ if resource_path == "res://":
995
+ return _failure("resource.properties requires resourcePath.", ["resource_path_missing"], _operation_help("resource.properties"))
996
+ var resource = load(resource_path)
997
+ if resource == null or not (resource is Resource):
998
+ return _failure("Resource could not be loaded: " + resource_path, ["resource_load_failed"])
999
+ var script = resource.get_script()
1000
+ var properties := _filter_property_list(resource.get_property_list(), str(operation.get("propertyQuery", "")), int(operation.get("propertyLimit", 80)))
1001
+ return _success("Resource properties loaded.", {"resourcePath": resource_path, "class": resource.get_class(), "scriptPath": script.resource_path if script else null, "properties": properties, "propertiesTruncated": properties.size() >= int(operation.get("propertyLimit", 80))})
1002
+
769
1003
  func _resource_set_property(operation: Dictionary) -> Dictionary:
770
1004
  var resource_path := _res_path(str(operation.get("resourcePath", "")))
771
1005
  var resource = load(resource_path)
@@ -871,13 +1105,34 @@ func _class_info(operation: Dictionary) -> Dictionary:
871
1105
  return _failure("Class not found: " + class_id, ["class_not_found"])
872
1106
 
873
1107
  func _editor_state(_operation: Dictionary) -> Dictionary:
1108
+ var editor_interface = _editor_interface()
1109
+ var current_scene_path = null
1110
+ var open_scenes := []
1111
+ var selected_node_paths := []
1112
+ if editor_interface != null:
1113
+ if editor_interface.has_method("get_open_scenes"):
1114
+ for scene_path in editor_interface.get_open_scenes():
1115
+ open_scenes.append(str(scene_path))
1116
+ var edited_root = editor_interface.get_edited_scene_root()
1117
+ if edited_root != null:
1118
+ current_scene_path = edited_root.scene_file_path
1119
+ var selection = editor_interface.get_selection()
1120
+ if selection != null:
1121
+ for selected_node in selection.get_selected_nodes():
1122
+ if edited_root != null and selected_node is Node:
1123
+ selected_node_paths.append(str(edited_root.get_path_to(selected_node)))
1124
+ else:
1125
+ selected_node_paths.append(str(selected_node.get_path()))
874
1126
  return _success("Editor state loaded.", {
875
1127
  "projectName": ProjectSettings.get_setting("application/config/name", ""),
876
1128
  "engineVersion": Engine.get_version_info().get("string", ""),
877
1129
  "features": ProjectSettings.get_setting("application/config/features", []),
878
1130
  "godotProjectRootPath": ProjectSettings.globalize_path("res://"),
1131
+ "editorContextAvailable": editor_interface != null,
1132
+ "currentScenePath": current_scene_path,
1133
+ "openScenes": open_scenes,
879
1134
  "dirtyScenes": [],
880
- "selectedNodePaths": [],
1135
+ "selectedNodePaths": selected_node_paths,
881
1136
  })
882
1137
 
883
1138
  func _batch_apply(operation: Dictionary) -> Dictionary:
@@ -940,23 +1195,67 @@ func _decode_value(value):
940
1195
  return Color(float(color.get("r", 0.0)), float(color.get("g", 0.0)), float(color.get("b", 0.0)), float(color.get("a", 1.0)))
941
1196
  return value
942
1197
 
943
- func _encode_value(value):
1198
+ func _encode_value(value, depth := 0):
944
1199
  if value == null:
945
1200
  return null
1201
+ if depth >= 4:
1202
+ return {"$truncated": "max_depth", "text": str(value)}
946
1203
  if value is Vector2:
947
1204
  return {"$vector2": {"x": value.x, "y": value.y}}
948
1205
  if value is Color:
949
1206
  return {"$color": {"r": value.r, "g": value.g, "b": value.b, "a": value.a}}
950
1207
  if value is Resource:
951
- return {"$resource": value.resource_path, "class": value.get_class()}
1208
+ var resource_path: String = value.resource_path
1209
+ return {"$resource": resource_path if resource_path != "" else null, "class": value.get_class(), "text": str(value)}
952
1210
  var value_type := typeof(value)
953
- if value_type in [TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_ARRAY, TYPE_DICTIONARY]:
1211
+ if value_type in [TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_STRING]:
954
1212
  return value
1213
+ if value_type == TYPE_ARRAY:
1214
+ var encoded := []
1215
+ var count := 0
1216
+ for item in value:
1217
+ if count >= 100:
1218
+ encoded.append({"$truncated": "max_items"})
1219
+ break
1220
+ encoded.append(_encode_value(item, depth + 1))
1221
+ count += 1
1222
+ return encoded
1223
+ if value_type == TYPE_DICTIONARY:
1224
+ var encoded_dict := {}
1225
+ var count := 0
1226
+ for key in value.keys():
1227
+ if count >= 100:
1228
+ encoded_dict["$truncated"] = "max_items"
1229
+ break
1230
+ encoded_dict[str(key)] = _encode_value(value[key], depth + 1)
1231
+ count += 1
1232
+ return encoded_dict
955
1233
  return str(value)
956
1234
 
957
1235
  func _property_summary(property: Dictionary) -> Dictionary:
958
1236
  return {"name": str(property.get("name", "")), "type": int(property.get("type", TYPE_NIL)), "hint": int(property.get("hint", 0)), "usage": int(property.get("usage", 0))}
959
1237
 
1238
+ func _filter_property_list(property_list: Array, query: String, limit: int) -> Array:
1239
+ var lowered_query := query.to_lower()
1240
+ var effective_limit := limit if limit > 0 else 50
1241
+ var properties := []
1242
+ for property in property_list:
1243
+ var name := str(property.get("name", ""))
1244
+ if lowered_query != "" and not name.to_lower().contains(lowered_query):
1245
+ continue
1246
+ properties.append(_property_summary(property))
1247
+ if properties.size() >= effective_limit:
1248
+ break
1249
+ return properties
1250
+
1251
+ func _editor_interface():
1252
+ var plugin = get("_plugin")
1253
+ if plugin == null:
1254
+ return null
1255
+ if plugin.has_method("get_editor_interface"):
1256
+ return plugin.get_editor_interface()
1257
+ return null
1258
+
960
1259
  func _find_script_class(class_id: String) -> Dictionary:
961
1260
  for entry in ProjectSettings.get_global_class_list():
962
1261
  if str(entry.get("class", "")) == class_id:
@@ -1048,8 +1347,25 @@ func _write_json(path: String, value: Dictionary) -> void:
1048
1347
  func _success(summary: String, output: Dictionary) -> Dictionary:
1049
1348
  return {"ok": true, "summary": summary, "reasons": [], "output": output}
1050
1349
 
1051
- func _failure(summary: String, reasons: Array) -> Dictionary:
1052
- return {"ok": false, "summary": summary, "reasons": reasons, "output": null}
1350
+ func _failure(summary: String, reasons: Array, help := {}) -> Dictionary:
1351
+ return {"ok": false, "summary": summary, "reasons": reasons, "output": null, "help": help}
1352
+
1353
+ func _operation_help(kind: String) -> Dictionary:
1354
+ var examples := {
1355
+ "scene.tree": {"kind": "scene.tree", "scenePath": "res://path/to/scene.tscn", "maxDepth": 3},
1356
+ "node.inspect": {"kind": "node.inspect", "scenePath": "res://path/to/scene.tscn", "nodePath": ".", "includePropertyList": true, "propertyLimit": 40},
1357
+ "resource.read": {"kind": "resource.read", "resourcePath": "res://path/to/resource.tres", "propertyNames": ["name"]},
1358
+ "resource.properties": {"kind": "resource.properties", "resourcePath": "res://path/to/resource.tres"},
1359
+ "class.search": {"kind": "class.search", "query": "Label"},
1360
+ "class.info": {"kind": "class.info", "className": "Label", "propertyQuery": "text"},
1361
+ "editor.state": {"kind": "editor.state"},
1362
+ }
1363
+ var example = examples.get(kind, {"kind": "editor.state"})
1364
+ return {
1365
+ "usage": "Use editor.operation.run with operation.kind, or prefer focused MCP tools: editor.state, editor.scene.tree, editor.node.inspect, editor.resource.read, editor.resource.properties, editor.class.search, editor.class.info.",
1366
+ "helpCommand": "gdh editor operation run --help",
1367
+ "examples": [example],
1368
+ }
1053
1369
  `;
1054
1370
  }
1055
1371
  export function renderEditorOperationCatalogGdscript() {