@skillcap/gdh 3.2.3 → 4.1.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.
- package/INSTALL-BUNDLE.json +1 -1
- package/README.md +6 -5
- package/RELEASE-SPAN-UPDATE-CONTRACTS.json +125 -0
- package/node_modules/@gdh/adapters/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/adapters/dist/index.js +0 -2
- package/node_modules/@gdh/adapters/dist/index.js.map +1 -1
- package/node_modules/@gdh/adapters/dist/skill-rendering.d.ts.map +1 -1
- package/node_modules/@gdh/adapters/dist/skill-rendering.js +26 -30
- package/node_modules/@gdh/adapters/dist/skill-rendering.js.map +1 -1
- package/node_modules/@gdh/adapters/package.json +7 -7
- package/node_modules/@gdh/authoring/dist/lsp.d.ts +12 -0
- package/node_modules/@gdh/authoring/dist/lsp.d.ts.map +1 -1
- package/node_modules/@gdh/authoring/dist/lsp.js +128 -3
- package/node_modules/@gdh/authoring/dist/lsp.js.map +1 -1
- package/node_modules/@gdh/authoring/package.json +2 -2
- package/node_modules/@gdh/cli/dist/bridge-session.d.ts.map +1 -1
- package/node_modules/@gdh/cli/dist/bridge-session.js +11 -25
- package/node_modules/@gdh/cli/dist/bridge-session.js.map +1 -1
- package/node_modules/@gdh/cli/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/cli/dist/index.js +26 -537
- package/node_modules/@gdh/cli/dist/index.js.map +1 -1
- package/node_modules/@gdh/cli/dist/migrate.d.ts.map +1 -1
- package/node_modules/@gdh/cli/dist/migrate.js +25 -0
- package/node_modules/@gdh/cli/dist/migrate.js.map +1 -1
- package/node_modules/@gdh/cli/package.json +11 -11
- package/node_modules/@gdh/core/dist/editor-operation-runner.d.ts.map +1 -1
- package/node_modules/@gdh/core/dist/editor-operation-runner.js +530 -1
- package/node_modules/@gdh/core/dist/editor-operation-runner.js.map +1 -1
- package/node_modules/@gdh/core/dist/index.d.ts +14 -10
- package/node_modules/@gdh/core/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/core/dist/index.js +16 -14
- package/node_modules/@gdh/core/dist/index.js.map +1 -1
- package/node_modules/@gdh/core/dist/migrations/entries/s3c26_to_s3c27_run_game_knowledge.d.ts +3 -0
- package/node_modules/@gdh/core/dist/migrations/entries/s3c26_to_s3c27_run_game_knowledge.d.ts.map +1 -0
- package/node_modules/@gdh/core/dist/migrations/entries/s3c26_to_s3c27_run_game_knowledge.js +91 -0
- package/node_modules/@gdh/core/dist/migrations/entries/s3c26_to_s3c27_run_game_knowledge.js.map +1 -0
- package/node_modules/@gdh/core/dist/migrations/managed-surface-classes.d.ts +7 -2
- package/node_modules/@gdh/core/dist/migrations/managed-surface-classes.d.ts.map +1 -1
- package/node_modules/@gdh/core/dist/migrations/managed-surface-classes.js +9 -3
- package/node_modules/@gdh/core/dist/migrations/managed-surface-classes.js.map +1 -1
- package/node_modules/@gdh/core/dist/migrations/managed-target-surface-inventory.d.ts +20 -9
- package/node_modules/@gdh/core/dist/migrations/managed-target-surface-inventory.d.ts.map +1 -1
- package/node_modules/@gdh/core/dist/migrations/managed-target-surface-inventory.js +22 -10
- package/node_modules/@gdh/core/dist/migrations/managed-target-surface-inventory.js.map +1 -1
- package/node_modules/@gdh/core/dist/migrations/registry.d.ts +1 -1
- package/node_modules/@gdh/core/dist/migrations/registry.d.ts.map +1 -1
- package/node_modules/@gdh/core/dist/migrations/registry.js +2 -0
- package/node_modules/@gdh/core/dist/migrations/registry.js.map +1 -1
- package/node_modules/@gdh/core/dist/run-game-knowledge-scaffold.d.ts +16 -0
- package/node_modules/@gdh/core/dist/run-game-knowledge-scaffold.d.ts.map +1 -0
- package/node_modules/@gdh/core/dist/run-game-knowledge-scaffold.js +89 -0
- package/node_modules/@gdh/core/dist/run-game-knowledge-scaffold.js.map +1 -0
- package/node_modules/@gdh/core/package.json +1 -1
- package/node_modules/@gdh/docs/dist/guidance.d.ts.map +1 -1
- package/node_modules/@gdh/docs/dist/guidance.js +29 -0
- package/node_modules/@gdh/docs/dist/guidance.js.map +1 -1
- package/node_modules/@gdh/docs/dist/templates/guidance/editor-bridge.md.tpl +4 -1
- package/node_modules/@gdh/docs/dist/templates/guidance/runtime.md.tpl +33 -0
- package/node_modules/@gdh/docs/package.json +2 -2
- package/node_modules/@gdh/editor/dist/index.d.ts +101 -0
- package/node_modules/@gdh/editor/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/editor/dist/index.js +166 -5
- package/node_modules/@gdh/editor/dist/index.js.map +1 -1
- package/node_modules/@gdh/editor/package.json +2 -2
- package/node_modules/@gdh/mcp/dist/bridge-tools.d.ts +3 -4
- package/node_modules/@gdh/mcp/dist/bridge-tools.d.ts.map +1 -1
- package/node_modules/@gdh/mcp/dist/bridge-tools.js +5 -77
- package/node_modules/@gdh/mcp/dist/bridge-tools.js.map +1 -1
- package/node_modules/@gdh/mcp/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/mcp/dist/index.js +832 -249
- package/node_modules/@gdh/mcp/dist/index.js.map +1 -1
- package/node_modules/@gdh/mcp/package.json +8 -8
- package/node_modules/@gdh/observability/package.json +2 -2
- package/node_modules/@gdh/runtime/dist/bridge-broker.d.ts +9 -1
- package/node_modules/@gdh/runtime/dist/bridge-broker.d.ts.map +1 -1
- package/node_modules/@gdh/runtime/dist/bridge-broker.js +267 -52
- package/node_modules/@gdh/runtime/dist/bridge-broker.js.map +1 -1
- package/node_modules/@gdh/runtime/dist/bridge-surface.js +11 -3
- package/node_modules/@gdh/runtime/dist/bridge-surface.js.map +1 -1
- package/node_modules/@gdh/runtime/package.json +2 -2
- package/node_modules/@gdh/scan/dist/onboard.d.ts.map +1 -1
- package/node_modules/@gdh/scan/dist/onboard.js +60 -180
- package/node_modules/@gdh/scan/dist/onboard.js.map +1 -1
- package/node_modules/@gdh/scan/package.json +3 -3
- package/node_modules/@gdh/verify/package.json +6 -6
- package/package.json +12 -12
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
1
3
|
import { doctorAuthoringDiagnostics, getAuthoringDiagnosticsStatus, getCurrentAuthoringDiagnostics, readProjectConfig, readWorktreeState, refreshAuthoringDiagnostics, resolveAuthoringStatus, resolveEffectiveTargetPath, resolveTargetGodotDocsVersion, runAuthoringCheck, runTargetPrepare, warmupManagedLsp, } from "@gdh/authoring";
|
|
2
4
|
import { definePackageBoundary, GDH_MCP_MANIFEST_VERSION, presentPublicRuntimeTerms, readGdhUpdateMetaOrNull, resolveGdhProductMetadata, } from "@gdh/core";
|
|
3
5
|
import { fetchOfficialGodotDoc, searchOfficialGodotDocs } from "@gdh/docs";
|
|
@@ -185,84 +187,599 @@ const TOOL_MANIFEST = [
|
|
|
185
187
|
outputContract: "GdhAuthoringLspWarmupResult",
|
|
186
188
|
},
|
|
187
189
|
{
|
|
188
|
-
name: "
|
|
189
|
-
summary: "
|
|
190
|
+
name: "editor.session.status",
|
|
191
|
+
summary: "Inspect whether GDH can run Godot-native editor operations for the exact bound target/worktree.",
|
|
192
|
+
targetPathPolicy: "optional",
|
|
193
|
+
inputSchema: defineObjectSchema("Editor Bridge session status request.", {
|
|
194
|
+
mode: {
|
|
195
|
+
type: "string",
|
|
196
|
+
description: "Optional session mode: auto, headless_only, adopt_only, or disabled. Defaults to auto.",
|
|
197
|
+
},
|
|
198
|
+
godotEditorBin: {
|
|
199
|
+
type: "string",
|
|
200
|
+
description: "Optional Godot editor executable override for this invocation.",
|
|
201
|
+
},
|
|
202
|
+
}),
|
|
203
|
+
outputSchema: outputEnvelopeSchema,
|
|
204
|
+
outputContract: "GdhEditorSessionSummary",
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
name: "editor.state",
|
|
208
|
+
summary: "Read current Godot editor context for the exact target/worktree: project state plus current/open scene and selection when an adopted editor exposes them.",
|
|
209
|
+
targetPathPolicy: "optional",
|
|
210
|
+
inputSchema: defineObjectSchema("Editor state request.", {
|
|
211
|
+
mode: {
|
|
212
|
+
type: "string",
|
|
213
|
+
description: "Optional session mode: auto, headless_only, adopt_only, or disabled. Use adopt_only when the user asks about the already-open editor.",
|
|
214
|
+
},
|
|
215
|
+
timeoutMs: {
|
|
216
|
+
type: "number",
|
|
217
|
+
description: "Optional positive timeout in milliseconds for the editor operation.",
|
|
218
|
+
},
|
|
219
|
+
godotEditorBin: {
|
|
220
|
+
type: "string",
|
|
221
|
+
description: "Optional Godot editor executable override for this invocation.",
|
|
222
|
+
},
|
|
223
|
+
}),
|
|
224
|
+
outputSchema: outputEnvelopeSchema,
|
|
225
|
+
outputContract: "GdhEditorOperationResult",
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
name: "editor.scene.tree",
|
|
229
|
+
summary: "Load one saved scene through Godot editor APIs and return a bounded node tree. Requires scenePath; use editor.state first when you need the active editor scene.",
|
|
230
|
+
targetPathPolicy: "optional",
|
|
231
|
+
inputSchema: defineObjectSchema("Editor scene tree request.", {
|
|
232
|
+
scenePath: {
|
|
233
|
+
type: "string",
|
|
234
|
+
description: "Required res:// path for the saved scene to load.",
|
|
235
|
+
},
|
|
236
|
+
maxDepth: {
|
|
237
|
+
type: "number",
|
|
238
|
+
description: "Optional positive depth limit for returned children.",
|
|
239
|
+
},
|
|
240
|
+
mode: {
|
|
241
|
+
type: "string",
|
|
242
|
+
description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
|
|
243
|
+
},
|
|
244
|
+
timeoutMs: {
|
|
245
|
+
type: "number",
|
|
246
|
+
description: "Optional positive timeout in milliseconds for the editor operation.",
|
|
247
|
+
},
|
|
248
|
+
godotEditorBin: {
|
|
249
|
+
type: "string",
|
|
250
|
+
description: "Optional Godot editor executable override for this invocation.",
|
|
251
|
+
},
|
|
252
|
+
}, ["scenePath"]),
|
|
253
|
+
outputSchema: outputEnvelopeSchema,
|
|
254
|
+
outputContract: "GdhEditorOperationResult",
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
name: "editor.node.inspect",
|
|
258
|
+
summary: "Inspect one node from a saved scene: node summary plus requested property values or a bounded inspector-style property list.",
|
|
259
|
+
targetPathPolicy: "optional",
|
|
260
|
+
inputSchema: defineObjectSchema("Editor node inspection request.", {
|
|
261
|
+
scenePath: {
|
|
262
|
+
type: "string",
|
|
263
|
+
description: "Required res:// path for the saved scene to load.",
|
|
264
|
+
},
|
|
265
|
+
nodePath: {
|
|
266
|
+
type: "string",
|
|
267
|
+
description: "Optional node path relative to the scene root. Defaults to root.",
|
|
268
|
+
},
|
|
269
|
+
propertyNames: stringArraySchema("Optional exact property names to read from the node."),
|
|
270
|
+
includePropertyList: {
|
|
271
|
+
type: "boolean",
|
|
272
|
+
description: "When true, return bounded property metadata similar to inspector discovery.",
|
|
273
|
+
},
|
|
274
|
+
propertyQuery: {
|
|
275
|
+
type: "string",
|
|
276
|
+
description: "Optional substring filter for returned property metadata.",
|
|
277
|
+
},
|
|
278
|
+
propertyLimit: {
|
|
279
|
+
type: "number",
|
|
280
|
+
description: "Optional positive limit for returned property metadata.",
|
|
281
|
+
},
|
|
282
|
+
mode: {
|
|
283
|
+
type: "string",
|
|
284
|
+
description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
|
|
285
|
+
},
|
|
286
|
+
timeoutMs: {
|
|
287
|
+
type: "number",
|
|
288
|
+
description: "Optional positive timeout in milliseconds for the editor operation.",
|
|
289
|
+
},
|
|
290
|
+
godotEditorBin: {
|
|
291
|
+
type: "string",
|
|
292
|
+
description: "Optional Godot editor executable override for this invocation.",
|
|
293
|
+
},
|
|
294
|
+
}, ["scenePath"]),
|
|
295
|
+
outputSchema: outputEnvelopeSchema,
|
|
296
|
+
outputContract: "GdhEditorOperationResult",
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
name: "editor.resource.read",
|
|
300
|
+
summary: "Read requested properties from one Godot resource via editor APIs. Nested arrays/dictionaries are encoded recursively with bounded resource handles.",
|
|
301
|
+
targetPathPolicy: "optional",
|
|
302
|
+
inputSchema: defineObjectSchema("Editor resource read request.", {
|
|
303
|
+
resourcePath: {
|
|
304
|
+
type: "string",
|
|
305
|
+
description: "Required res:// resource path, including ::subresource id when needed.",
|
|
306
|
+
},
|
|
307
|
+
propertyNames: stringArraySchema("Optional exact property names to read from the resource."),
|
|
308
|
+
mode: {
|
|
309
|
+
type: "string",
|
|
310
|
+
description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
|
|
311
|
+
},
|
|
312
|
+
timeoutMs: {
|
|
313
|
+
type: "number",
|
|
314
|
+
description: "Optional positive timeout in milliseconds for the editor operation.",
|
|
315
|
+
},
|
|
316
|
+
godotEditorBin: {
|
|
317
|
+
type: "string",
|
|
318
|
+
description: "Optional Godot editor executable override for this invocation.",
|
|
319
|
+
},
|
|
320
|
+
}, ["resourcePath"]),
|
|
321
|
+
outputSchema: outputEnvelopeSchema,
|
|
322
|
+
outputContract: "GdhEditorOperationResult",
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
name: "editor.resource.properties",
|
|
326
|
+
summary: "Discover bounded property metadata for one Godot resource before choosing propertyNames for editor.resource.read.",
|
|
327
|
+
targetPathPolicy: "optional",
|
|
328
|
+
inputSchema: defineObjectSchema("Editor resource property discovery request.", {
|
|
329
|
+
resourcePath: {
|
|
330
|
+
type: "string",
|
|
331
|
+
description: "Required res:// resource path, including ::subresource id when needed.",
|
|
332
|
+
},
|
|
333
|
+
propertyQuery: {
|
|
334
|
+
type: "string",
|
|
335
|
+
description: "Optional substring filter for returned property metadata.",
|
|
336
|
+
},
|
|
337
|
+
propertyLimit: {
|
|
338
|
+
type: "number",
|
|
339
|
+
description: "Optional positive limit for returned property metadata.",
|
|
340
|
+
},
|
|
341
|
+
mode: {
|
|
342
|
+
type: "string",
|
|
343
|
+
description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
|
|
344
|
+
},
|
|
345
|
+
timeoutMs: {
|
|
346
|
+
type: "number",
|
|
347
|
+
description: "Optional positive timeout in milliseconds for the editor operation.",
|
|
348
|
+
},
|
|
349
|
+
godotEditorBin: {
|
|
350
|
+
type: "string",
|
|
351
|
+
description: "Optional Godot editor executable override for this invocation.",
|
|
352
|
+
},
|
|
353
|
+
}, ["resourcePath"]),
|
|
354
|
+
outputSchema: outputEnvelopeSchema,
|
|
355
|
+
outputContract: "GdhEditorOperationResult",
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
name: "editor.class.search",
|
|
359
|
+
summary: "Search Godot ClassDB and registered script classes with bounded query controls.",
|
|
190
360
|
targetPathPolicy: "optional",
|
|
191
|
-
inputSchema: defineObjectSchema("
|
|
192
|
-
|
|
361
|
+
inputSchema: defineObjectSchema("Editor class search request.", {
|
|
362
|
+
query: {
|
|
363
|
+
type: "string",
|
|
364
|
+
description: "Optional substring query for class names.",
|
|
365
|
+
},
|
|
366
|
+
baseClass: {
|
|
367
|
+
type: "string",
|
|
368
|
+
description: "Optional base class filter.",
|
|
369
|
+
},
|
|
370
|
+
instantiableOnly: {
|
|
371
|
+
type: "boolean",
|
|
372
|
+
description: "When false, include non-instantiable classes. Defaults to true.",
|
|
373
|
+
},
|
|
374
|
+
limit: {
|
|
375
|
+
type: "number",
|
|
376
|
+
description: "Optional positive result limit.",
|
|
377
|
+
},
|
|
378
|
+
mode: {
|
|
379
|
+
type: "string",
|
|
380
|
+
description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
|
|
381
|
+
},
|
|
382
|
+
timeoutMs: {
|
|
383
|
+
type: "number",
|
|
384
|
+
description: "Optional positive timeout in milliseconds for the editor operation.",
|
|
385
|
+
},
|
|
386
|
+
godotEditorBin: {
|
|
387
|
+
type: "string",
|
|
388
|
+
description: "Optional Godot editor executable override for this invocation.",
|
|
389
|
+
},
|
|
390
|
+
}),
|
|
391
|
+
outputSchema: outputEnvelopeSchema,
|
|
392
|
+
outputContract: "GdhEditorOperationResult",
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
name: "editor.class.info",
|
|
396
|
+
summary: "Return bounded property metadata for one Godot or registered script class.",
|
|
397
|
+
targetPathPolicy: "optional",
|
|
398
|
+
inputSchema: defineObjectSchema("Editor class info request.", {
|
|
399
|
+
className: {
|
|
400
|
+
type: "string",
|
|
401
|
+
description: "Required Godot or registered script class name.",
|
|
402
|
+
},
|
|
403
|
+
includeInherited: {
|
|
404
|
+
type: "boolean",
|
|
405
|
+
description: "When true, include inherited properties. Defaults to true.",
|
|
406
|
+
},
|
|
407
|
+
propertyQuery: {
|
|
408
|
+
type: "string",
|
|
409
|
+
description: "Optional substring filter for returned property metadata.",
|
|
410
|
+
},
|
|
411
|
+
propertyLimit: {
|
|
412
|
+
type: "number",
|
|
413
|
+
description: "Optional positive property metadata limit.",
|
|
414
|
+
},
|
|
415
|
+
mode: {
|
|
416
|
+
type: "string",
|
|
417
|
+
description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
|
|
418
|
+
},
|
|
419
|
+
timeoutMs: {
|
|
420
|
+
type: "number",
|
|
421
|
+
description: "Optional positive timeout in milliseconds for the editor operation.",
|
|
422
|
+
},
|
|
423
|
+
godotEditorBin: {
|
|
424
|
+
type: "string",
|
|
425
|
+
description: "Optional Godot editor executable override for this invocation.",
|
|
426
|
+
},
|
|
427
|
+
}, ["className"]),
|
|
428
|
+
outputSchema: outputEnvelopeSchema,
|
|
429
|
+
outputContract: "GdhEditorOperationResult",
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
name: "editor.animation.player.inspect",
|
|
433
|
+
summary: "Inspect an AnimationPlayer or AnimationMixer node in a saved scene, including libraries, clips, autoplay, and blend metadata.",
|
|
434
|
+
targetPathPolicy: "optional",
|
|
435
|
+
inputSchema: defineObjectSchema("Editor animation player inspection request.", {
|
|
436
|
+
scenePath: {
|
|
437
|
+
type: "string",
|
|
438
|
+
description: "Required res:// path for the saved scene to load.",
|
|
439
|
+
},
|
|
440
|
+
animationPlayerPath: {
|
|
441
|
+
type: "string",
|
|
442
|
+
description: "Required node path to the AnimationPlayer or AnimationMixer.",
|
|
443
|
+
},
|
|
444
|
+
mode: {
|
|
445
|
+
type: "string",
|
|
446
|
+
description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
|
|
447
|
+
},
|
|
448
|
+
timeoutMs: {
|
|
449
|
+
type: "number",
|
|
450
|
+
description: "Optional positive timeout in milliseconds for the editor operation.",
|
|
451
|
+
},
|
|
452
|
+
godotEditorBin: {
|
|
453
|
+
type: "string",
|
|
454
|
+
description: "Optional Godot editor executable override for this invocation.",
|
|
455
|
+
},
|
|
456
|
+
}, ["scenePath", "animationPlayerPath"]),
|
|
457
|
+
outputSchema: outputEnvelopeSchema,
|
|
458
|
+
outputContract: "GdhEditorOperationResult",
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
name: "editor.animation.clip.read",
|
|
462
|
+
summary: "Read one AnimationPlayer clip through Godot APIs, including tracks and optionally bounded keyframe data.",
|
|
463
|
+
targetPathPolicy: "optional",
|
|
464
|
+
inputSchema: defineObjectSchema("Editor animation clip read request.", {
|
|
465
|
+
scenePath: {
|
|
466
|
+
type: "string",
|
|
467
|
+
description: "Required res:// path for the saved scene to load.",
|
|
468
|
+
},
|
|
469
|
+
animationPlayerPath: {
|
|
470
|
+
type: "string",
|
|
471
|
+
description: "Required node path to the AnimationPlayer or AnimationMixer.",
|
|
472
|
+
},
|
|
473
|
+
libraryName: {
|
|
474
|
+
type: "string",
|
|
475
|
+
description: "Optional AnimationLibrary name. Defaults to the global empty-name library.",
|
|
476
|
+
},
|
|
477
|
+
animationName: {
|
|
478
|
+
type: "string",
|
|
479
|
+
description: "Required animation key inside the selected library.",
|
|
480
|
+
},
|
|
481
|
+
includeKeys: {
|
|
482
|
+
type: "boolean",
|
|
483
|
+
description: "When true, include bounded keyframe data for each returned track.",
|
|
484
|
+
},
|
|
485
|
+
keyLimit: {
|
|
486
|
+
type: "number",
|
|
487
|
+
description: "Optional positive keyframe limit across each track.",
|
|
488
|
+
},
|
|
489
|
+
mode: {
|
|
490
|
+
type: "string",
|
|
491
|
+
description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
|
|
492
|
+
},
|
|
493
|
+
timeoutMs: {
|
|
494
|
+
type: "number",
|
|
495
|
+
description: "Optional positive timeout in milliseconds for the editor operation.",
|
|
496
|
+
},
|
|
497
|
+
godotEditorBin: {
|
|
498
|
+
type: "string",
|
|
499
|
+
description: "Optional Godot editor executable override for this invocation.",
|
|
500
|
+
},
|
|
501
|
+
}, ["scenePath", "animationPlayerPath", "animationName"]),
|
|
502
|
+
outputSchema: outputEnvelopeSchema,
|
|
503
|
+
outputContract: "GdhEditorOperationResult",
|
|
504
|
+
},
|
|
505
|
+
{
|
|
506
|
+
name: "editor.animation.clip.create",
|
|
507
|
+
summary: "Create or overwrite one AnimationPlayer clip in an AnimationLibrary through Godot editor APIs.",
|
|
508
|
+
targetPathPolicy: "optional",
|
|
509
|
+
inputSchema: defineObjectSchema("Editor animation clip create request.", {
|
|
510
|
+
scenePath: {
|
|
511
|
+
type: "string",
|
|
512
|
+
description: "Required res:// path for the saved scene to load.",
|
|
513
|
+
},
|
|
514
|
+
animationPlayerPath: {
|
|
515
|
+
type: "string",
|
|
516
|
+
description: "Required node path to the AnimationPlayer or AnimationMixer.",
|
|
517
|
+
},
|
|
518
|
+
libraryName: {
|
|
519
|
+
type: "string",
|
|
520
|
+
description: "Optional AnimationLibrary name. Defaults to the global empty-name library.",
|
|
521
|
+
},
|
|
522
|
+
animationName: {
|
|
523
|
+
type: "string",
|
|
524
|
+
description: "Required animation key inside the selected library.",
|
|
525
|
+
},
|
|
526
|
+
length: {
|
|
527
|
+
type: "number",
|
|
528
|
+
description: "Optional animation length in seconds. Defaults to 1.0.",
|
|
529
|
+
},
|
|
530
|
+
step: {
|
|
531
|
+
type: "number",
|
|
532
|
+
description: "Optional animation step in seconds.",
|
|
533
|
+
},
|
|
534
|
+
loopMode: {
|
|
535
|
+
type: ["string", "number"],
|
|
536
|
+
description: "Optional loop mode: none, linear, pingpong, or a Godot numeric value.",
|
|
537
|
+
},
|
|
538
|
+
overwrite: {
|
|
539
|
+
type: "boolean",
|
|
540
|
+
description: "When true, replace an existing clip with the same name.",
|
|
541
|
+
},
|
|
542
|
+
mode: {
|
|
543
|
+
type: "string",
|
|
544
|
+
description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
|
|
545
|
+
},
|
|
546
|
+
timeoutMs: {
|
|
547
|
+
type: "number",
|
|
548
|
+
description: "Optional positive timeout in milliseconds for the editor operation.",
|
|
549
|
+
},
|
|
550
|
+
godotEditorBin: {
|
|
551
|
+
type: "string",
|
|
552
|
+
description: "Optional Godot editor executable override for this invocation.",
|
|
553
|
+
},
|
|
554
|
+
}, ["scenePath", "animationPlayerPath", "animationName"]),
|
|
555
|
+
outputSchema: outputEnvelopeSchema,
|
|
556
|
+
outputContract: "GdhEditorOperationResult",
|
|
557
|
+
},
|
|
558
|
+
{
|
|
559
|
+
name: "editor.animation.clip.delete",
|
|
560
|
+
summary: "Delete one AnimationPlayer clip from an AnimationLibrary through Godot editor APIs.",
|
|
561
|
+
targetPathPolicy: "optional",
|
|
562
|
+
inputSchema: defineObjectSchema("Editor animation clip delete request.", {
|
|
563
|
+
scenePath: {
|
|
564
|
+
type: "string",
|
|
565
|
+
description: "Required res:// path for the saved scene to load.",
|
|
566
|
+
},
|
|
567
|
+
animationPlayerPath: {
|
|
568
|
+
type: "string",
|
|
569
|
+
description: "Required node path to the AnimationPlayer or AnimationMixer.",
|
|
570
|
+
},
|
|
571
|
+
libraryName: {
|
|
572
|
+
type: "string",
|
|
573
|
+
description: "Optional AnimationLibrary name. Defaults to the global empty-name library.",
|
|
574
|
+
},
|
|
575
|
+
animationName: {
|
|
576
|
+
type: "string",
|
|
577
|
+
description: "Required animation key inside the selected library.",
|
|
578
|
+
},
|
|
579
|
+
mode: {
|
|
580
|
+
type: "string",
|
|
581
|
+
description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
|
|
582
|
+
},
|
|
583
|
+
timeoutMs: {
|
|
584
|
+
type: "number",
|
|
585
|
+
description: "Optional positive timeout in milliseconds for the editor operation.",
|
|
586
|
+
},
|
|
587
|
+
godotEditorBin: {
|
|
588
|
+
type: "string",
|
|
589
|
+
description: "Optional Godot editor executable override for this invocation.",
|
|
590
|
+
},
|
|
591
|
+
}, ["scenePath", "animationPlayerPath", "animationName"]),
|
|
592
|
+
outputSchema: outputEnvelopeSchema,
|
|
593
|
+
outputContract: "GdhEditorOperationResult",
|
|
594
|
+
},
|
|
595
|
+
{
|
|
596
|
+
name: "editor.animation.track.add",
|
|
597
|
+
summary: "Add a typed Animation track to one clip, using Godot track types and a NodePath such as Sprite2D:modulate:a.",
|
|
598
|
+
targetPathPolicy: "optional",
|
|
599
|
+
inputSchema: defineObjectSchema("Editor animation track add request.", {
|
|
600
|
+
scenePath: {
|
|
601
|
+
type: "string",
|
|
602
|
+
description: "Required res:// path for the saved scene to load.",
|
|
603
|
+
},
|
|
604
|
+
animationPlayerPath: {
|
|
605
|
+
type: "string",
|
|
606
|
+
description: "Required node path to the AnimationPlayer or AnimationMixer.",
|
|
607
|
+
},
|
|
608
|
+
libraryName: {
|
|
609
|
+
type: "string",
|
|
610
|
+
description: "Optional AnimationLibrary name. Defaults to the global empty-name library.",
|
|
611
|
+
},
|
|
612
|
+
animationName: {
|
|
613
|
+
type: "string",
|
|
614
|
+
description: "Required animation key inside the selected library.",
|
|
615
|
+
},
|
|
616
|
+
trackType: {
|
|
617
|
+
type: ["string", "number"],
|
|
618
|
+
description: "Optional Godot Animation track type. Use value, position_3d, rotation_3d, scale_3d, blend_shape, method, bezier, audio, or animation. Defaults to value.",
|
|
619
|
+
},
|
|
620
|
+
trackPath: {
|
|
621
|
+
type: "string",
|
|
622
|
+
description: "Required Animation track NodePath, relative to the AnimationPlayer root.",
|
|
623
|
+
},
|
|
624
|
+
atPosition: {
|
|
625
|
+
type: "number",
|
|
626
|
+
description: "Optional zero-based insertion position. Defaults to appending the track.",
|
|
627
|
+
},
|
|
628
|
+
interpolation: {
|
|
629
|
+
type: ["string", "number"],
|
|
630
|
+
description: "Optional interpolation: nearest, linear, cubic, linear_angle, cubic_angle, or a Godot numeric value.",
|
|
631
|
+
},
|
|
632
|
+
updateMode: {
|
|
633
|
+
type: ["string", "number"],
|
|
634
|
+
description: "Optional value-track update mode: continuous, discrete, capture, or a Godot numeric value.",
|
|
635
|
+
},
|
|
636
|
+
mode: {
|
|
637
|
+
type: "string",
|
|
638
|
+
description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
|
|
639
|
+
},
|
|
640
|
+
timeoutMs: {
|
|
641
|
+
type: "number",
|
|
642
|
+
description: "Optional positive timeout in milliseconds for the editor operation.",
|
|
643
|
+
},
|
|
644
|
+
godotEditorBin: {
|
|
645
|
+
type: "string",
|
|
646
|
+
description: "Optional Godot editor executable override for this invocation.",
|
|
647
|
+
},
|
|
648
|
+
}, ["scenePath", "animationPlayerPath", "animationName", "trackPath"]),
|
|
649
|
+
outputSchema: outputEnvelopeSchema,
|
|
650
|
+
outputContract: "GdhEditorOperationResult",
|
|
651
|
+
},
|
|
652
|
+
{
|
|
653
|
+
name: "editor.animation.track.remove",
|
|
654
|
+
summary: "Remove one track from an AnimationPlayer clip by zero-based track index.",
|
|
655
|
+
targetPathPolicy: "optional",
|
|
656
|
+
inputSchema: defineObjectSchema("Editor animation track remove request.", {
|
|
657
|
+
scenePath: {
|
|
658
|
+
type: "string",
|
|
659
|
+
description: "Required res:// path for the saved scene to load.",
|
|
660
|
+
},
|
|
661
|
+
animationPlayerPath: {
|
|
662
|
+
type: "string",
|
|
663
|
+
description: "Required node path to the AnimationPlayer or AnimationMixer.",
|
|
664
|
+
},
|
|
665
|
+
libraryName: {
|
|
666
|
+
type: "string",
|
|
667
|
+
description: "Optional AnimationLibrary name. Defaults to the global empty-name library.",
|
|
668
|
+
},
|
|
669
|
+
animationName: {
|
|
193
670
|
type: "string",
|
|
194
|
-
description: "
|
|
671
|
+
description: "Required animation key inside the selected library.",
|
|
195
672
|
},
|
|
196
|
-
|
|
673
|
+
trackIndex: {
|
|
674
|
+
type: "number",
|
|
675
|
+
description: "Required zero-based track index.",
|
|
676
|
+
},
|
|
677
|
+
mode: {
|
|
197
678
|
type: "string",
|
|
198
|
-
description: "Optional
|
|
679
|
+
description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
|
|
199
680
|
},
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
environment: stringMapSchema("Environment variable overrides keyed by variable name."),
|
|
204
|
-
liveWorkspace: {
|
|
205
|
-
type: "boolean",
|
|
206
|
-
description: "When true, evaluate the run configuration against the live workspace instead of an isolated copy.",
|
|
681
|
+
timeoutMs: {
|
|
682
|
+
type: "number",
|
|
683
|
+
description: "Optional positive timeout in milliseconds for the editor operation.",
|
|
207
684
|
},
|
|
208
|
-
|
|
685
|
+
godotEditorBin: {
|
|
686
|
+
type: "string",
|
|
687
|
+
description: "Optional Godot editor executable override for this invocation.",
|
|
688
|
+
},
|
|
689
|
+
}, ["scenePath", "animationPlayerPath", "animationName", "trackIndex"]),
|
|
209
690
|
outputSchema: outputEnvelopeSchema,
|
|
210
|
-
outputContract: "
|
|
691
|
+
outputContract: "GdhEditorOperationResult",
|
|
211
692
|
},
|
|
212
693
|
{
|
|
213
|
-
name: "
|
|
214
|
-
summary: "
|
|
694
|
+
name: "editor.animation.keyframe.upsert",
|
|
695
|
+
summary: "Insert or replace one keyframe on an Animation track. Values use GDH's encoded Variant shape for vectors, colors, resources, and scalars.",
|
|
215
696
|
targetPathPolicy: "optional",
|
|
216
|
-
inputSchema: defineObjectSchema("
|
|
217
|
-
|
|
697
|
+
inputSchema: defineObjectSchema("Editor animation keyframe upsert request.", {
|
|
698
|
+
scenePath: {
|
|
218
699
|
type: "string",
|
|
219
|
-
description: "
|
|
700
|
+
description: "Required res:// path for the saved scene to load.",
|
|
220
701
|
},
|
|
221
|
-
|
|
702
|
+
animationPlayerPath: {
|
|
222
703
|
type: "string",
|
|
223
|
-
description: "
|
|
704
|
+
description: "Required node path to the AnimationPlayer or AnimationMixer.",
|
|
224
705
|
},
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
environment: stringMapSchema("Environment variable overrides keyed by variable name."),
|
|
229
|
-
liveWorkspace: {
|
|
230
|
-
type: "boolean",
|
|
231
|
-
description: "When true, execute against the live workspace instead of an isolated copy.",
|
|
706
|
+
libraryName: {
|
|
707
|
+
type: "string",
|
|
708
|
+
description: "Optional AnimationLibrary name. Defaults to the global empty-name library.",
|
|
232
709
|
},
|
|
233
|
-
|
|
234
|
-
type: "
|
|
235
|
-
description: "
|
|
710
|
+
animationName: {
|
|
711
|
+
type: "string",
|
|
712
|
+
description: "Required animation key inside the selected library.",
|
|
713
|
+
},
|
|
714
|
+
trackIndex: {
|
|
715
|
+
type: "number",
|
|
716
|
+
description: "Required zero-based track index.",
|
|
717
|
+
},
|
|
718
|
+
time: {
|
|
719
|
+
type: "number",
|
|
720
|
+
description: "Required key time in seconds.",
|
|
721
|
+
},
|
|
722
|
+
value: {
|
|
723
|
+
type: ["string", "number", "boolean", "object", "array"],
|
|
724
|
+
description: "Required key value as a JSON-serializable Godot Variant encoding.",
|
|
725
|
+
additionalProperties: true,
|
|
726
|
+
},
|
|
727
|
+
transition: {
|
|
728
|
+
type: "number",
|
|
729
|
+
description: "Optional key transition value. Defaults to 1.0.",
|
|
236
730
|
},
|
|
237
|
-
}, ["runConfigurationId"]),
|
|
238
|
-
outputSchema: outputEnvelopeSchema,
|
|
239
|
-
outputContract: "GdhRuntimeRecipeRunResult",
|
|
240
|
-
},
|
|
241
|
-
{
|
|
242
|
-
name: "editor.session.status",
|
|
243
|
-
summary: "Inspect whether GDH can run Godot-native editor operations for the exact bound target/worktree.",
|
|
244
|
-
targetPathPolicy: "optional",
|
|
245
|
-
inputSchema: defineObjectSchema("Editor Bridge session status request.", {
|
|
246
731
|
mode: {
|
|
247
732
|
type: "string",
|
|
248
|
-
description: "Optional session mode: auto, headless_only, adopt_only, or disabled.
|
|
733
|
+
description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
|
|
734
|
+
},
|
|
735
|
+
timeoutMs: {
|
|
736
|
+
type: "number",
|
|
737
|
+
description: "Optional positive timeout in milliseconds for the editor operation.",
|
|
249
738
|
},
|
|
250
739
|
godotEditorBin: {
|
|
251
740
|
type: "string",
|
|
252
741
|
description: "Optional Godot editor executable override for this invocation.",
|
|
253
742
|
},
|
|
254
|
-
}),
|
|
743
|
+
}, ["scenePath", "animationPlayerPath", "animationName", "trackIndex", "time", "value"]),
|
|
255
744
|
outputSchema: outputEnvelopeSchema,
|
|
256
|
-
outputContract: "
|
|
745
|
+
outputContract: "GdhEditorOperationResult",
|
|
257
746
|
},
|
|
258
747
|
{
|
|
259
|
-
name: "editor.
|
|
260
|
-
summary: "
|
|
748
|
+
name: "editor.animation.keyframe.delete",
|
|
749
|
+
summary: "Delete one keyframe from an Animation track by key index or key time.",
|
|
261
750
|
targetPathPolicy: "optional",
|
|
262
|
-
inputSchema: defineObjectSchema("Editor
|
|
751
|
+
inputSchema: defineObjectSchema("Editor animation keyframe delete request.", {
|
|
752
|
+
scenePath: {
|
|
753
|
+
type: "string",
|
|
754
|
+
description: "Required res:// path for the saved scene to load.",
|
|
755
|
+
},
|
|
756
|
+
animationPlayerPath: {
|
|
757
|
+
type: "string",
|
|
758
|
+
description: "Required node path to the AnimationPlayer or AnimationMixer.",
|
|
759
|
+
},
|
|
760
|
+
libraryName: {
|
|
761
|
+
type: "string",
|
|
762
|
+
description: "Optional AnimationLibrary name. Defaults to the global empty-name library.",
|
|
763
|
+
},
|
|
764
|
+
animationName: {
|
|
765
|
+
type: "string",
|
|
766
|
+
description: "Required animation key inside the selected library.",
|
|
767
|
+
},
|
|
768
|
+
trackIndex: {
|
|
769
|
+
type: "number",
|
|
770
|
+
description: "Required zero-based track index.",
|
|
771
|
+
},
|
|
772
|
+
keyIndex: {
|
|
773
|
+
type: "number",
|
|
774
|
+
description: "Optional zero-based key index. Provide keyIndex or time.",
|
|
775
|
+
},
|
|
776
|
+
time: {
|
|
777
|
+
type: "number",
|
|
778
|
+
description: "Optional key time in seconds. Provide keyIndex or time.",
|
|
779
|
+
},
|
|
263
780
|
mode: {
|
|
264
781
|
type: "string",
|
|
265
|
-
description: "Optional session mode: auto, headless_only, adopt_only, or disabled.
|
|
782
|
+
description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
|
|
266
783
|
},
|
|
267
784
|
timeoutMs: {
|
|
268
785
|
type: "number",
|
|
@@ -272,22 +789,31 @@ const TOOL_MANIFEST = [
|
|
|
272
789
|
type: "string",
|
|
273
790
|
description: "Optional Godot editor executable override for this invocation.",
|
|
274
791
|
},
|
|
275
|
-
}),
|
|
792
|
+
}, ["scenePath", "animationPlayerPath", "animationName", "trackIndex"]),
|
|
276
793
|
outputSchema: outputEnvelopeSchema,
|
|
277
794
|
outputContract: "GdhEditorOperationResult",
|
|
278
795
|
},
|
|
279
796
|
{
|
|
280
|
-
name: "editor.
|
|
281
|
-
summary: "
|
|
797
|
+
name: "editor.animation.state_machine.create",
|
|
798
|
+
summary: "Create an AnimationNodeStateMachine tree_root on an AnimationTree node through Godot editor APIs.",
|
|
282
799
|
targetPathPolicy: "optional",
|
|
283
|
-
inputSchema: defineObjectSchema("Editor
|
|
800
|
+
inputSchema: defineObjectSchema("Editor animation state-machine create request.", {
|
|
284
801
|
scenePath: {
|
|
285
802
|
type: "string",
|
|
286
803
|
description: "Required res:// path for the saved scene to load.",
|
|
287
804
|
},
|
|
288
|
-
|
|
289
|
-
type: "
|
|
290
|
-
description: "
|
|
805
|
+
animationTreePath: {
|
|
806
|
+
type: "string",
|
|
807
|
+
description: "Required node path to the AnimationTree.",
|
|
808
|
+
},
|
|
809
|
+
overwrite: {
|
|
810
|
+
type: "boolean",
|
|
811
|
+
description: "When true, replace an existing AnimationNodeStateMachine tree_root.",
|
|
812
|
+
},
|
|
813
|
+
properties: {
|
|
814
|
+
type: "object",
|
|
815
|
+
description: "Optional properties to set on the AnimationNodeStateMachine resource.",
|
|
816
|
+
additionalProperties: true,
|
|
291
817
|
},
|
|
292
818
|
mode: {
|
|
293
819
|
type: "string",
|
|
@@ -301,35 +827,22 @@ const TOOL_MANIFEST = [
|
|
|
301
827
|
type: "string",
|
|
302
828
|
description: "Optional Godot editor executable override for this invocation.",
|
|
303
829
|
},
|
|
304
|
-
}, ["scenePath"]),
|
|
830
|
+
}, ["scenePath", "animationTreePath"]),
|
|
305
831
|
outputSchema: outputEnvelopeSchema,
|
|
306
832
|
outputContract: "GdhEditorOperationResult",
|
|
307
833
|
},
|
|
308
834
|
{
|
|
309
|
-
name: "editor.
|
|
310
|
-
summary: "
|
|
835
|
+
name: "editor.animation.state_machine.read",
|
|
836
|
+
summary: "Read an AnimationTree state-machine graph as compact nodes and transitions without automating the editor UI.",
|
|
311
837
|
targetPathPolicy: "optional",
|
|
312
|
-
inputSchema: defineObjectSchema("Editor
|
|
838
|
+
inputSchema: defineObjectSchema("Editor animation state-machine graph read request.", {
|
|
313
839
|
scenePath: {
|
|
314
840
|
type: "string",
|
|
315
841
|
description: "Required res:// path for the saved scene to load.",
|
|
316
842
|
},
|
|
317
|
-
|
|
318
|
-
type: "string",
|
|
319
|
-
description: "Optional node path relative to the scene root. Defaults to root.",
|
|
320
|
-
},
|
|
321
|
-
propertyNames: stringArraySchema("Optional exact property names to read from the node."),
|
|
322
|
-
includePropertyList: {
|
|
323
|
-
type: "boolean",
|
|
324
|
-
description: "When true, return bounded property metadata similar to inspector discovery.",
|
|
325
|
-
},
|
|
326
|
-
propertyQuery: {
|
|
843
|
+
animationTreePath: {
|
|
327
844
|
type: "string",
|
|
328
|
-
description: "
|
|
329
|
-
},
|
|
330
|
-
propertyLimit: {
|
|
331
|
-
type: "number",
|
|
332
|
-
description: "Optional positive limit for returned property metadata.",
|
|
845
|
+
description: "Required node path to the AnimationTree with an AnimationNodeStateMachine tree_root.",
|
|
333
846
|
},
|
|
334
847
|
mode: {
|
|
335
848
|
type: "string",
|
|
@@ -343,20 +856,41 @@ const TOOL_MANIFEST = [
|
|
|
343
856
|
type: "string",
|
|
344
857
|
description: "Optional Godot editor executable override for this invocation.",
|
|
345
858
|
},
|
|
346
|
-
}, ["scenePath"]),
|
|
859
|
+
}, ["scenePath", "animationTreePath"]),
|
|
347
860
|
outputSchema: outputEnvelopeSchema,
|
|
348
861
|
outputContract: "GdhEditorOperationResult",
|
|
349
862
|
},
|
|
350
863
|
{
|
|
351
|
-
name: "editor.
|
|
352
|
-
summary: "
|
|
864
|
+
name: "editor.animation.state_machine.node.upsert",
|
|
865
|
+
summary: "Create or update one node in an AnimationTree state-machine graph without automating the editor UI.",
|
|
353
866
|
targetPathPolicy: "optional",
|
|
354
|
-
inputSchema: defineObjectSchema("Editor
|
|
355
|
-
|
|
867
|
+
inputSchema: defineObjectSchema("Editor animation state-machine node upsert request.", {
|
|
868
|
+
scenePath: {
|
|
356
869
|
type: "string",
|
|
357
|
-
description: "Required res://
|
|
870
|
+
description: "Required res:// path for the saved scene to load.",
|
|
871
|
+
},
|
|
872
|
+
animationTreePath: {
|
|
873
|
+
type: "string",
|
|
874
|
+
description: "Required node path to the AnimationTree.",
|
|
875
|
+
},
|
|
876
|
+
stateName: {
|
|
877
|
+
type: "string",
|
|
878
|
+
description: "Required state-machine node name.",
|
|
879
|
+
},
|
|
880
|
+
nodeType: {
|
|
881
|
+
type: "string",
|
|
882
|
+
description: "Optional AnimationNode type. Defaults to AnimationNodeAnimation.",
|
|
883
|
+
},
|
|
884
|
+
position: {
|
|
885
|
+
type: "object",
|
|
886
|
+
description: 'Optional graph position encoded as {"$vector2":{"x":0,"y":0}}.',
|
|
887
|
+
additionalProperties: true,
|
|
888
|
+
},
|
|
889
|
+
properties: {
|
|
890
|
+
type: "object",
|
|
891
|
+
description: 'Optional properties to set on the AnimationNode, for example {"animation":"idle"}.',
|
|
892
|
+
additionalProperties: true,
|
|
358
893
|
},
|
|
359
|
-
propertyNames: stringArraySchema("Optional exact property names to read from the resource."),
|
|
360
894
|
mode: {
|
|
361
895
|
type: "string",
|
|
362
896
|
description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
|
|
@@ -369,26 +903,26 @@ const TOOL_MANIFEST = [
|
|
|
369
903
|
type: "string",
|
|
370
904
|
description: "Optional Godot editor executable override for this invocation.",
|
|
371
905
|
},
|
|
372
|
-
}, ["
|
|
906
|
+
}, ["scenePath", "animationTreePath", "stateName"]),
|
|
373
907
|
outputSchema: outputEnvelopeSchema,
|
|
374
908
|
outputContract: "GdhEditorOperationResult",
|
|
375
909
|
},
|
|
376
910
|
{
|
|
377
|
-
name: "editor.
|
|
378
|
-
summary: "
|
|
911
|
+
name: "editor.animation.state_machine.node.delete",
|
|
912
|
+
summary: "Delete one node from an AnimationTree state-machine graph.",
|
|
379
913
|
targetPathPolicy: "optional",
|
|
380
|
-
inputSchema: defineObjectSchema("Editor
|
|
381
|
-
|
|
914
|
+
inputSchema: defineObjectSchema("Editor animation state-machine node delete request.", {
|
|
915
|
+
scenePath: {
|
|
382
916
|
type: "string",
|
|
383
|
-
description: "Required res://
|
|
917
|
+
description: "Required res:// path for the saved scene to load.",
|
|
384
918
|
},
|
|
385
|
-
|
|
919
|
+
animationTreePath: {
|
|
386
920
|
type: "string",
|
|
387
|
-
description: "
|
|
921
|
+
description: "Required node path to the AnimationTree.",
|
|
388
922
|
},
|
|
389
|
-
|
|
390
|
-
type: "
|
|
391
|
-
description: "
|
|
923
|
+
stateName: {
|
|
924
|
+
type: "string",
|
|
925
|
+
description: "Required state-machine node name.",
|
|
392
926
|
},
|
|
393
927
|
mode: {
|
|
394
928
|
type: "string",
|
|
@@ -402,30 +936,35 @@ const TOOL_MANIFEST = [
|
|
|
402
936
|
type: "string",
|
|
403
937
|
description: "Optional Godot editor executable override for this invocation.",
|
|
404
938
|
},
|
|
405
|
-
}, ["
|
|
939
|
+
}, ["scenePath", "animationTreePath", "stateName"]),
|
|
406
940
|
outputSchema: outputEnvelopeSchema,
|
|
407
941
|
outputContract: "GdhEditorOperationResult",
|
|
408
942
|
},
|
|
409
943
|
{
|
|
410
|
-
name: "editor.
|
|
411
|
-
summary: "
|
|
944
|
+
name: "editor.animation.state_machine.transition.upsert",
|
|
945
|
+
summary: "Create or replace one transition in an AnimationTree state-machine graph without automating the editor UI.",
|
|
412
946
|
targetPathPolicy: "optional",
|
|
413
|
-
inputSchema: defineObjectSchema("Editor
|
|
414
|
-
|
|
947
|
+
inputSchema: defineObjectSchema("Editor animation state-machine transition upsert request.", {
|
|
948
|
+
scenePath: {
|
|
415
949
|
type: "string",
|
|
416
|
-
description: "
|
|
950
|
+
description: "Required res:// path for the saved scene to load.",
|
|
417
951
|
},
|
|
418
|
-
|
|
952
|
+
animationTreePath: {
|
|
419
953
|
type: "string",
|
|
420
|
-
description: "
|
|
954
|
+
description: "Required node path to the AnimationTree.",
|
|
421
955
|
},
|
|
422
|
-
|
|
423
|
-
type: "
|
|
424
|
-
description: "
|
|
956
|
+
fromState: {
|
|
957
|
+
type: "string",
|
|
958
|
+
description: "Required source state name.",
|
|
425
959
|
},
|
|
426
|
-
|
|
427
|
-
type: "
|
|
428
|
-
description: "
|
|
960
|
+
toState: {
|
|
961
|
+
type: "string",
|
|
962
|
+
description: "Required target state name.",
|
|
963
|
+
},
|
|
964
|
+
properties: {
|
|
965
|
+
type: "object",
|
|
966
|
+
description: "Optional properties to set on the transition resource.",
|
|
967
|
+
additionalProperties: true,
|
|
429
968
|
},
|
|
430
969
|
mode: {
|
|
431
970
|
type: "string",
|
|
@@ -439,30 +978,30 @@ const TOOL_MANIFEST = [
|
|
|
439
978
|
type: "string",
|
|
440
979
|
description: "Optional Godot editor executable override for this invocation.",
|
|
441
980
|
},
|
|
442
|
-
}),
|
|
981
|
+
}, ["scenePath", "animationTreePath", "fromState", "toState"]),
|
|
443
982
|
outputSchema: outputEnvelopeSchema,
|
|
444
983
|
outputContract: "GdhEditorOperationResult",
|
|
445
984
|
},
|
|
446
985
|
{
|
|
447
|
-
name: "editor.
|
|
448
|
-
summary: "
|
|
986
|
+
name: "editor.animation.state_machine.transition.delete",
|
|
987
|
+
summary: "Delete one transition from an AnimationTree state-machine graph.",
|
|
449
988
|
targetPathPolicy: "optional",
|
|
450
|
-
inputSchema: defineObjectSchema("Editor
|
|
451
|
-
|
|
989
|
+
inputSchema: defineObjectSchema("Editor animation state-machine transition delete request.", {
|
|
990
|
+
scenePath: {
|
|
452
991
|
type: "string",
|
|
453
|
-
description: "Required
|
|
992
|
+
description: "Required res:// path for the saved scene to load.",
|
|
454
993
|
},
|
|
455
|
-
|
|
456
|
-
type: "
|
|
457
|
-
description: "
|
|
994
|
+
animationTreePath: {
|
|
995
|
+
type: "string",
|
|
996
|
+
description: "Required node path to the AnimationTree.",
|
|
458
997
|
},
|
|
459
|
-
|
|
998
|
+
fromState: {
|
|
460
999
|
type: "string",
|
|
461
|
-
description: "
|
|
1000
|
+
description: "Required source state name.",
|
|
462
1001
|
},
|
|
463
|
-
|
|
464
|
-
type: "
|
|
465
|
-
description: "
|
|
1002
|
+
toState: {
|
|
1003
|
+
type: "string",
|
|
1004
|
+
description: "Required target state name.",
|
|
466
1005
|
},
|
|
467
1006
|
mode: {
|
|
468
1007
|
type: "string",
|
|
@@ -476,13 +1015,13 @@ const TOOL_MANIFEST = [
|
|
|
476
1015
|
type: "string",
|
|
477
1016
|
description: "Optional Godot editor executable override for this invocation.",
|
|
478
1017
|
},
|
|
479
|
-
}, ["
|
|
1018
|
+
}, ["scenePath", "animationTreePath", "fromState", "toState"]),
|
|
480
1019
|
outputSchema: outputEnvelopeSchema,
|
|
481
1020
|
outputContract: "GdhEditorOperationResult",
|
|
482
1021
|
},
|
|
483
1022
|
{
|
|
484
1023
|
name: "editor.operation.run",
|
|
485
|
-
summary: "Advanced escape hatch for one targeted Godot-native editor operation. Prefer focused editor.* tools for normal reads. Payloads dispatch on operation.kind, not type.",
|
|
1024
|
+
summary: "Advanced escape hatch for one targeted Godot-native editor operation. Prefer focused editor.* tools for normal reads and common writes. Payloads dispatch on operation.kind, not type.",
|
|
486
1025
|
targetPathPolicy: "optional",
|
|
487
1026
|
inputSchema: defineObjectSchema("Editor Bridge operation request.", {
|
|
488
1027
|
operation: {
|
|
@@ -516,69 +1055,15 @@ const TOOL_MANIFEST = [
|
|
|
516
1055
|
stringArraySchema,
|
|
517
1056
|
stringMapSchema,
|
|
518
1057
|
}),
|
|
519
|
-
{
|
|
520
|
-
name: "verify.run",
|
|
521
|
-
summary: "Execute one verification scenario over a run configuration and return the structured run record.",
|
|
522
|
-
targetPathPolicy: "optional",
|
|
523
|
-
inputSchema: defineObjectSchema("Runtime verification execution request.", {
|
|
524
|
-
runConfigurationId: {
|
|
525
|
-
type: "string",
|
|
526
|
-
description: "Run configuration id to execute.",
|
|
527
|
-
},
|
|
528
|
-
verificationScenarioId: {
|
|
529
|
-
type: "string",
|
|
530
|
-
description: "Verification scenario id to run over the selected run configuration.",
|
|
531
|
-
},
|
|
532
|
-
provider: {
|
|
533
|
-
type: "string",
|
|
534
|
-
description: "Optional provider id to force when a run configuration supports multiple providers.",
|
|
535
|
-
},
|
|
536
|
-
parameters: stringMapSchema("Optional parameter overrides keyed by parameter id."),
|
|
537
|
-
enabledFeatures: stringArraySchema("Feature flag ids to force on for this verification run."),
|
|
538
|
-
disabledFeatures: stringArraySchema("Feature flag ids to force off for this verification run."),
|
|
539
|
-
environment: stringMapSchema("Environment variable overrides keyed by variable name."),
|
|
540
|
-
liveWorkspace: {
|
|
541
|
-
type: "boolean",
|
|
542
|
-
description: "When true, execute against the live workspace instead of an isolated copy.",
|
|
543
|
-
},
|
|
544
|
-
renderedScreenshot: {
|
|
545
|
-
type: "boolean",
|
|
546
|
-
description: "When true, request one rendered screenshot artifact for this verification run when the selected runtime path can capture it.",
|
|
547
|
-
},
|
|
548
|
-
}, ["runConfigurationId", "verificationScenarioId"]),
|
|
549
|
-
outputSchema: outputEnvelopeSchema,
|
|
550
|
-
outputContract: "GdhRuntimeRunBundle",
|
|
551
|
-
},
|
|
552
1058
|
];
|
|
553
1059
|
const RESOURCE_MANIFEST = [
|
|
554
1060
|
{
|
|
555
|
-
name: "run-
|
|
556
|
-
summary: "Read
|
|
557
|
-
mimeType: "
|
|
558
|
-
uri: "gdh://run-
|
|
559
|
-
uriTemplate: null,
|
|
560
|
-
},
|
|
561
|
-
{
|
|
562
|
-
name: "run-configuration",
|
|
563
|
-
summary: "Read one run configuration for the bound target by id as structured JSON.",
|
|
564
|
-
mimeType: "application/json",
|
|
565
|
-
uri: null,
|
|
566
|
-
uriTemplate: "gdh://run-configurations/{id}",
|
|
567
|
-
},
|
|
568
|
-
{
|
|
569
|
-
name: "verification-scenarios",
|
|
570
|
-
summary: "Read the discovered verification scenarios for the bound target as structured JSON.",
|
|
571
|
-
mimeType: "application/json",
|
|
572
|
-
uri: "gdh://verification-scenarios",
|
|
1061
|
+
name: "run-game-knowledge",
|
|
1062
|
+
summary: "Read project-owned guidance for how agents should run this Godot target.",
|
|
1063
|
+
mimeType: "text/markdown",
|
|
1064
|
+
uri: "gdh://runtime-knowledge/run-game",
|
|
573
1065
|
uriTemplate: null,
|
|
574
1066
|
},
|
|
575
|
-
{
|
|
576
|
-
name: "verification-scenario",
|
|
577
|
-
summary: "Read one verification scenario for the bound target by id as structured JSON.",
|
|
578
|
-
mimeType: "application/json",
|
|
579
|
-
uri: null,
|
|
580
|
-
uriTemplate: "gdh://verification-scenarios/{id}",
|
|
581
|
-
},
|
|
582
1067
|
];
|
|
583
1068
|
export function listMcpTools() {
|
|
584
1069
|
return TOOL_MANIFEST;
|
|
@@ -757,10 +1242,6 @@ async function invokeMcpToolWithContext(request, context) {
|
|
|
757
1242
|
return succeeded(request.toolName, targetPath, await invokeAuthoringDiagnosticsDoctorTool(targetPath));
|
|
758
1243
|
case "authoring.warmup":
|
|
759
1244
|
return succeeded(request.toolName, targetPath, await invokeAuthoringWarmupTool(targetPath, request.input));
|
|
760
|
-
case "run-config.check":
|
|
761
|
-
return succeeded(request.toolName, targetPath, await invokeRunConfigCheckTool(targetPath, request.input));
|
|
762
|
-
case "run-config.run":
|
|
763
|
-
return succeeded(request.toolName, targetPath, await invokeRunConfigRunTool(targetPath, request.input));
|
|
764
1245
|
case "editor.session.status":
|
|
765
1246
|
return succeeded(request.toolName, targetPath, await invokeEditorSessionStatusTool(targetPath, request.input));
|
|
766
1247
|
case "editor.state":
|
|
@@ -807,19 +1288,139 @@ async function invokeMcpToolWithContext(request, context) {
|
|
|
807
1288
|
propertyQuery: readOptionalString(request.input["propertyQuery"], "propertyQuery"),
|
|
808
1289
|
propertyLimit: readOptionalPositiveInteger(request.input["propertyLimit"], "propertyLimit"),
|
|
809
1290
|
})));
|
|
1291
|
+
case "editor.animation.player.inspect":
|
|
1292
|
+
return succeeded(request.toolName, targetPath, await invokeFocusedEditorOperationTool(targetPath, request.input, createEditorOperation("animation.player.inspect", {
|
|
1293
|
+
scenePath: requireString(request.input["scenePath"], "scenePath"),
|
|
1294
|
+
animationPlayerPath: requireString(request.input["animationPlayerPath"], "animationPlayerPath"),
|
|
1295
|
+
})));
|
|
1296
|
+
case "editor.animation.clip.read":
|
|
1297
|
+
return succeeded(request.toolName, targetPath, await invokeFocusedEditorOperationTool(targetPath, request.input, createEditorOperation("animation.clip.read", {
|
|
1298
|
+
scenePath: requireString(request.input["scenePath"], "scenePath"),
|
|
1299
|
+
animationPlayerPath: requireString(request.input["animationPlayerPath"], "animationPlayerPath"),
|
|
1300
|
+
libraryName: readOptionalString(request.input["libraryName"], "libraryName"),
|
|
1301
|
+
animationName: requireString(request.input["animationName"], "animationName"),
|
|
1302
|
+
includeKeys: readOptionalBoolean(request.input["includeKeys"], "includeKeys"),
|
|
1303
|
+
keyLimit: readOptionalPositiveInteger(request.input["keyLimit"], "keyLimit"),
|
|
1304
|
+
})));
|
|
1305
|
+
case "editor.animation.clip.create":
|
|
1306
|
+
return succeeded(request.toolName, targetPath, await invokeFocusedEditorOperationTool(targetPath, request.input, createEditorOperation("animation.clip.create", {
|
|
1307
|
+
scenePath: requireString(request.input["scenePath"], "scenePath"),
|
|
1308
|
+
animationPlayerPath: requireString(request.input["animationPlayerPath"], "animationPlayerPath"),
|
|
1309
|
+
libraryName: readOptionalString(request.input["libraryName"], "libraryName"),
|
|
1310
|
+
animationName: requireString(request.input["animationName"], "animationName"),
|
|
1311
|
+
length: readOptionalNumber(request.input["length"], "length"),
|
|
1312
|
+
step: readOptionalNumber(request.input["step"], "step"),
|
|
1313
|
+
loopMode: readOptionalStringOrNumber(request.input["loopMode"], "loopMode"),
|
|
1314
|
+
overwrite: readOptionalBoolean(request.input["overwrite"], "overwrite"),
|
|
1315
|
+
})));
|
|
1316
|
+
case "editor.animation.clip.delete":
|
|
1317
|
+
return succeeded(request.toolName, targetPath, await invokeFocusedEditorOperationTool(targetPath, request.input, createEditorOperation("animation.clip.delete", {
|
|
1318
|
+
scenePath: requireString(request.input["scenePath"], "scenePath"),
|
|
1319
|
+
animationPlayerPath: requireString(request.input["animationPlayerPath"], "animationPlayerPath"),
|
|
1320
|
+
libraryName: readOptionalString(request.input["libraryName"], "libraryName"),
|
|
1321
|
+
animationName: requireString(request.input["animationName"], "animationName"),
|
|
1322
|
+
})));
|
|
1323
|
+
case "editor.animation.track.add":
|
|
1324
|
+
return succeeded(request.toolName, targetPath, await invokeFocusedEditorOperationTool(targetPath, request.input, createEditorOperation("animation.track.add", {
|
|
1325
|
+
scenePath: requireString(request.input["scenePath"], "scenePath"),
|
|
1326
|
+
animationPlayerPath: requireString(request.input["animationPlayerPath"], "animationPlayerPath"),
|
|
1327
|
+
libraryName: readOptionalString(request.input["libraryName"], "libraryName"),
|
|
1328
|
+
animationName: requireString(request.input["animationName"], "animationName"),
|
|
1329
|
+
trackType: readOptionalStringOrNumber(request.input["trackType"], "trackType") ?? "value",
|
|
1330
|
+
trackPath: requireString(request.input["trackPath"], "trackPath"),
|
|
1331
|
+
atPosition: readOptionalNumber(request.input["atPosition"], "atPosition"),
|
|
1332
|
+
interpolation: readOptionalStringOrNumber(request.input["interpolation"], "interpolation"),
|
|
1333
|
+
updateMode: readOptionalStringOrNumber(request.input["updateMode"], "updateMode"),
|
|
1334
|
+
})));
|
|
1335
|
+
case "editor.animation.track.remove":
|
|
1336
|
+
return succeeded(request.toolName, targetPath, await invokeFocusedEditorOperationTool(targetPath, request.input, createEditorOperation("animation.track.remove", {
|
|
1337
|
+
scenePath: requireString(request.input["scenePath"], "scenePath"),
|
|
1338
|
+
animationPlayerPath: requireString(request.input["animationPlayerPath"], "animationPlayerPath"),
|
|
1339
|
+
libraryName: readOptionalString(request.input["libraryName"], "libraryName"),
|
|
1340
|
+
animationName: requireString(request.input["animationName"], "animationName"),
|
|
1341
|
+
trackIndex: requireNumber(request.input["trackIndex"], "trackIndex"),
|
|
1342
|
+
})));
|
|
1343
|
+
case "editor.animation.keyframe.upsert":
|
|
1344
|
+
return succeeded(request.toolName, targetPath, await invokeFocusedEditorOperationTool(targetPath, request.input, createEditorOperation("animation.keyframe.upsert", {
|
|
1345
|
+
scenePath: requireString(request.input["scenePath"], "scenePath"),
|
|
1346
|
+
animationPlayerPath: requireString(request.input["animationPlayerPath"], "animationPlayerPath"),
|
|
1347
|
+
libraryName: readOptionalString(request.input["libraryName"], "libraryName"),
|
|
1348
|
+
animationName: requireString(request.input["animationName"], "animationName"),
|
|
1349
|
+
trackIndex: requireNumber(request.input["trackIndex"], "trackIndex"),
|
|
1350
|
+
time: requireNumber(request.input["time"], "time"),
|
|
1351
|
+
value: requireJsonValue(request.input["value"], "value"),
|
|
1352
|
+
transition: readOptionalNumber(request.input["transition"], "transition"),
|
|
1353
|
+
})));
|
|
1354
|
+
case "editor.animation.keyframe.delete":
|
|
1355
|
+
return succeeded(request.toolName, targetPath, await invokeFocusedEditorOperationTool(targetPath, request.input, createEditorOperation("animation.keyframe.delete", {
|
|
1356
|
+
scenePath: requireString(request.input["scenePath"], "scenePath"),
|
|
1357
|
+
animationPlayerPath: requireString(request.input["animationPlayerPath"], "animationPlayerPath"),
|
|
1358
|
+
libraryName: readOptionalString(request.input["libraryName"], "libraryName"),
|
|
1359
|
+
animationName: requireString(request.input["animationName"], "animationName"),
|
|
1360
|
+
trackIndex: requireNumber(request.input["trackIndex"], "trackIndex"),
|
|
1361
|
+
keyIndex: readOptionalNumber(request.input["keyIndex"], "keyIndex"),
|
|
1362
|
+
time: readOptionalNumber(request.input["time"], "time"),
|
|
1363
|
+
})));
|
|
1364
|
+
case "editor.animation.state_machine.create":
|
|
1365
|
+
return succeeded(request.toolName, targetPath, await invokeFocusedEditorOperationTool(targetPath, request.input, createEditorOperation("animation.state_machine.create", {
|
|
1366
|
+
scenePath: requireString(request.input["scenePath"], "scenePath"),
|
|
1367
|
+
animationTreePath: requireString(request.input["animationTreePath"], "animationTreePath"),
|
|
1368
|
+
overwrite: readOptionalBoolean(request.input["overwrite"], "overwrite"),
|
|
1369
|
+
properties: request.input["properties"] === undefined
|
|
1370
|
+
? undefined
|
|
1371
|
+
: requireObject(request.input["properties"], "properties"),
|
|
1372
|
+
})));
|
|
1373
|
+
case "editor.animation.state_machine.read":
|
|
1374
|
+
return succeeded(request.toolName, targetPath, await invokeFocusedEditorOperationTool(targetPath, request.input, createEditorOperation("animation.state_machine.read", {
|
|
1375
|
+
scenePath: requireString(request.input["scenePath"], "scenePath"),
|
|
1376
|
+
animationTreePath: requireString(request.input["animationTreePath"], "animationTreePath"),
|
|
1377
|
+
})));
|
|
1378
|
+
case "editor.animation.state_machine.node.upsert":
|
|
1379
|
+
return succeeded(request.toolName, targetPath, await invokeFocusedEditorOperationTool(targetPath, request.input, createEditorOperation("animation.state_machine.node.upsert", {
|
|
1380
|
+
scenePath: requireString(request.input["scenePath"], "scenePath"),
|
|
1381
|
+
animationTreePath: requireString(request.input["animationTreePath"], "animationTreePath"),
|
|
1382
|
+
stateName: requireString(request.input["stateName"], "stateName"),
|
|
1383
|
+
nodeType: readOptionalString(request.input["nodeType"], "nodeType"),
|
|
1384
|
+
position: request.input["position"] === undefined
|
|
1385
|
+
? undefined
|
|
1386
|
+
: requireJsonValue(request.input["position"], "position"),
|
|
1387
|
+
properties: request.input["properties"] === undefined
|
|
1388
|
+
? undefined
|
|
1389
|
+
: requireObject(request.input["properties"], "properties"),
|
|
1390
|
+
})));
|
|
1391
|
+
case "editor.animation.state_machine.node.delete":
|
|
1392
|
+
return succeeded(request.toolName, targetPath, await invokeFocusedEditorOperationTool(targetPath, request.input, createEditorOperation("animation.state_machine.node.delete", {
|
|
1393
|
+
scenePath: requireString(request.input["scenePath"], "scenePath"),
|
|
1394
|
+
animationTreePath: requireString(request.input["animationTreePath"], "animationTreePath"),
|
|
1395
|
+
stateName: requireString(request.input["stateName"], "stateName"),
|
|
1396
|
+
})));
|
|
1397
|
+
case "editor.animation.state_machine.transition.upsert":
|
|
1398
|
+
return succeeded(request.toolName, targetPath, await invokeFocusedEditorOperationTool(targetPath, request.input, createEditorOperation("animation.state_machine.transition.upsert", {
|
|
1399
|
+
scenePath: requireString(request.input["scenePath"], "scenePath"),
|
|
1400
|
+
animationTreePath: requireString(request.input["animationTreePath"], "animationTreePath"),
|
|
1401
|
+
fromState: requireString(request.input["fromState"], "fromState"),
|
|
1402
|
+
toState: requireString(request.input["toState"], "toState"),
|
|
1403
|
+
properties: request.input["properties"] === undefined
|
|
1404
|
+
? undefined
|
|
1405
|
+
: requireObject(request.input["properties"], "properties"),
|
|
1406
|
+
})));
|
|
1407
|
+
case "editor.animation.state_machine.transition.delete":
|
|
1408
|
+
return succeeded(request.toolName, targetPath, await invokeFocusedEditorOperationTool(targetPath, request.input, createEditorOperation("animation.state_machine.transition.delete", {
|
|
1409
|
+
scenePath: requireString(request.input["scenePath"], "scenePath"),
|
|
1410
|
+
animationTreePath: requireString(request.input["animationTreePath"], "animationTreePath"),
|
|
1411
|
+
fromState: requireString(request.input["fromState"], "fromState"),
|
|
1412
|
+
toState: requireString(request.input["toState"], "toState"),
|
|
1413
|
+
})));
|
|
810
1414
|
case "editor.operation.run":
|
|
811
1415
|
return succeeded(request.toolName, targetPath, await invokeEditorOperationRunTool(targetPath, request.input));
|
|
812
|
-
case "bridge.session.start":
|
|
813
|
-
return succeeded(request.toolName, targetPath, await invokeBridgeTool(request.toolName, targetPath, request.input, context));
|
|
814
1416
|
case "bridge.entry.list":
|
|
815
1417
|
return succeeded(request.toolName, targetPath, await invokeBridgeTool(request.toolName, targetPath, request.input, context));
|
|
816
1418
|
case "bridge.entry.invoke":
|
|
817
1419
|
return succeeded(request.toolName, targetPath, await invokeBridgeTool(request.toolName, targetPath, request.input, context));
|
|
818
1420
|
case "bridge.session.stop":
|
|
819
1421
|
return succeeded(request.toolName, targetPath, await invokeBridgeTool(request.toolName, targetPath, request.input, context));
|
|
820
|
-
case "verify.run":
|
|
821
|
-
return succeeded(request.toolName, targetPath, await invokeVerifyRunTool(targetPath, request.input));
|
|
822
1422
|
}
|
|
1423
|
+
return failed(request.toolName, targetPath, `Unknown GDH MCP tool: ${request.toolName}`);
|
|
823
1424
|
}
|
|
824
1425
|
catch (error) {
|
|
825
1426
|
return failed(request.toolName, targetPath, formatMcpError(error));
|
|
@@ -833,75 +1434,26 @@ async function resolveMcpTargetPath(targetPath) {
|
|
|
833
1434
|
}
|
|
834
1435
|
async function listMcpResources(targetPath) {
|
|
835
1436
|
const effectiveTargetPath = await resolveMcpTargetPath(targetPath);
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
listRuntimeRecipes({ targetPath: effectiveTargetPath, projectConfig }),
|
|
839
|
-
listRuntimeScenarios({ targetPath: effectiveTargetPath }),
|
|
840
|
-
]);
|
|
841
|
-
const resources = [
|
|
842
|
-
{
|
|
843
|
-
uri: "gdh://run-configurations",
|
|
844
|
-
name: "run-configurations",
|
|
845
|
-
description: "Discovered run configurations for the bound target.",
|
|
846
|
-
mimeType: "application/json",
|
|
847
|
-
},
|
|
1437
|
+
void effectiveTargetPath;
|
|
1438
|
+
return [
|
|
848
1439
|
{
|
|
849
|
-
uri: "gdh://
|
|
850
|
-
name: "
|
|
851
|
-
description: "
|
|
852
|
-
mimeType: "
|
|
1440
|
+
uri: "gdh://runtime-knowledge/run-game",
|
|
1441
|
+
name: "run-game-knowledge",
|
|
1442
|
+
description: "Project-owned guidance for how agents should run this Godot target.",
|
|
1443
|
+
mimeType: "text/markdown",
|
|
853
1444
|
},
|
|
854
1445
|
];
|
|
855
|
-
for (const runConfiguration of runConfigurations.recipes) {
|
|
856
|
-
resources.push({
|
|
857
|
-
uri: buildRunConfigurationUri(runConfiguration.id),
|
|
858
|
-
name: `run-configuration:${runConfiguration.id}`,
|
|
859
|
-
description: `Run configuration "${runConfiguration.id}" for the bound target.`,
|
|
860
|
-
mimeType: "application/json",
|
|
861
|
-
});
|
|
862
|
-
}
|
|
863
|
-
for (const verificationScenario of verificationScenarios.scenarios) {
|
|
864
|
-
resources.push({
|
|
865
|
-
uri: buildVerificationScenarioUri(verificationScenario.id),
|
|
866
|
-
name: `verification-scenario:${verificationScenario.id}`,
|
|
867
|
-
description: `Verification scenario "${verificationScenario.id}" for the bound target.`,
|
|
868
|
-
mimeType: "application/json",
|
|
869
|
-
});
|
|
870
|
-
}
|
|
871
|
-
return resources;
|
|
872
1446
|
}
|
|
873
1447
|
async function readMcpResource(targetPath, uri) {
|
|
874
1448
|
const effectiveTargetPath = await resolveMcpTargetPath(targetPath);
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
return presentPublicRuntimeTerms(await listRuntimeScenarios({ targetPath: effectiveTargetPath }));
|
|
881
|
-
}
|
|
882
|
-
const runConfigurationId = parseResourceId(uri, "gdh://run-configurations/");
|
|
883
|
-
if (runConfigurationId !== null) {
|
|
884
|
-
return presentPublicRuntimeTerms(await showRuntimeRecipe({
|
|
885
|
-
targetPath: effectiveTargetPath,
|
|
886
|
-
projectConfig,
|
|
887
|
-
recipeId: runConfigurationId,
|
|
888
|
-
}));
|
|
889
|
-
}
|
|
890
|
-
const verificationScenarioId = parseResourceId(uri, "gdh://verification-scenarios/");
|
|
891
|
-
if (verificationScenarioId !== null) {
|
|
892
|
-
return presentPublicRuntimeTerms(await showRuntimeScenario({
|
|
893
|
-
targetPath: effectiveTargetPath,
|
|
894
|
-
scenarioId: verificationScenarioId,
|
|
895
|
-
}));
|
|
1449
|
+
if (uri === "gdh://runtime-knowledge/run-game") {
|
|
1450
|
+
const projectConfig = await readProjectConfig(effectiveTargetPath);
|
|
1451
|
+
const knowledgePath = projectConfig?.runtimeKnowledge.path ?? ".gdh/runtime-knowledge";
|
|
1452
|
+
const runGamePath = path.join(effectiveTargetPath, knowledgePath, "run-game.md");
|
|
1453
|
+
return await fs.readFile(runGamePath, "utf8");
|
|
896
1454
|
}
|
|
897
1455
|
throw new Error(`Unknown GDH MCP resource: ${uri}`);
|
|
898
1456
|
}
|
|
899
|
-
function buildRunConfigurationUri(runConfigurationId) {
|
|
900
|
-
return `gdh://run-configurations/${encodeURIComponent(runConfigurationId)}`;
|
|
901
|
-
}
|
|
902
|
-
function buildVerificationScenarioUri(verificationScenarioId) {
|
|
903
|
-
return `gdh://verification-scenarios/${encodeURIComponent(verificationScenarioId)}`;
|
|
904
|
-
}
|
|
905
1457
|
function parseResourceId(uri, prefix) {
|
|
906
1458
|
if (!uri.startsWith(prefix)) {
|
|
907
1459
|
return null;
|
|
@@ -1245,6 +1797,15 @@ function readOptionalString(value, fieldName) {
|
|
|
1245
1797
|
}
|
|
1246
1798
|
return value;
|
|
1247
1799
|
}
|
|
1800
|
+
function readOptionalStringOrNumber(value, fieldName) {
|
|
1801
|
+
if (value === undefined || value === null) {
|
|
1802
|
+
return undefined;
|
|
1803
|
+
}
|
|
1804
|
+
if (typeof value !== "string" && typeof value !== "number") {
|
|
1805
|
+
throw new Error(`MCP input field "${fieldName}" must be a string or number.`);
|
|
1806
|
+
}
|
|
1807
|
+
return value;
|
|
1808
|
+
}
|
|
1248
1809
|
function readOptionalEditorSessionMode(value, fieldName) {
|
|
1249
1810
|
const mode = readOptionalString(value, fieldName);
|
|
1250
1811
|
if (mode === null || mode === "auto")
|
|
@@ -1264,6 +1825,28 @@ function requireString(value, fieldName) {
|
|
|
1264
1825
|
}
|
|
1265
1826
|
return stringValue;
|
|
1266
1827
|
}
|
|
1828
|
+
function readOptionalNumber(value, fieldName) {
|
|
1829
|
+
if (value === undefined) {
|
|
1830
|
+
return undefined;
|
|
1831
|
+
}
|
|
1832
|
+
if (typeof value !== "number") {
|
|
1833
|
+
throw new Error(`MCP input field "${fieldName}" must be a number.`);
|
|
1834
|
+
}
|
|
1835
|
+
return value;
|
|
1836
|
+
}
|
|
1837
|
+
function requireNumber(value, fieldName) {
|
|
1838
|
+
const numberValue = readOptionalNumber(value, fieldName);
|
|
1839
|
+
if (numberValue === undefined) {
|
|
1840
|
+
throw new Error(`MCP input field "${fieldName}" is required.`);
|
|
1841
|
+
}
|
|
1842
|
+
return numberValue;
|
|
1843
|
+
}
|
|
1844
|
+
function requireJsonValue(value, fieldName) {
|
|
1845
|
+
if (value === undefined) {
|
|
1846
|
+
throw new Error(`MCP input field "${fieldName}" is required.`);
|
|
1847
|
+
}
|
|
1848
|
+
return value;
|
|
1849
|
+
}
|
|
1267
1850
|
function requireObject(value, fieldName) {
|
|
1268
1851
|
if (value === undefined) {
|
|
1269
1852
|
throw new Error(`MCP input field "${fieldName}" is required.`);
|