@skillcap/gdh 4.0.0 → 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.
Files changed (39) hide show
  1. package/INSTALL-BUNDLE.json +1 -1
  2. package/RELEASE-SPAN-UPDATE-CONTRACTS.json +69 -0
  3. package/node_modules/@gdh/adapters/package.json +7 -7
  4. package/node_modules/@gdh/authoring/dist/lsp.d.ts +12 -0
  5. package/node_modules/@gdh/authoring/dist/lsp.d.ts.map +1 -1
  6. package/node_modules/@gdh/authoring/dist/lsp.js +128 -3
  7. package/node_modules/@gdh/authoring/dist/lsp.js.map +1 -1
  8. package/node_modules/@gdh/authoring/package.json +2 -2
  9. package/node_modules/@gdh/cli/package.json +11 -11
  10. package/node_modules/@gdh/core/dist/editor-operation-runner.d.ts.map +1 -1
  11. package/node_modules/@gdh/core/dist/editor-operation-runner.js +530 -1
  12. package/node_modules/@gdh/core/dist/editor-operation-runner.js.map +1 -1
  13. package/node_modules/@gdh/core/dist/index.d.ts +8 -8
  14. package/node_modules/@gdh/core/dist/index.d.ts.map +1 -1
  15. package/node_modules/@gdh/core/dist/index.js +10 -5
  16. package/node_modules/@gdh/core/dist/index.js.map +1 -1
  17. package/node_modules/@gdh/core/package.json +1 -1
  18. package/node_modules/@gdh/docs/dist/templates/guidance/editor-bridge.md.tpl +4 -1
  19. package/node_modules/@gdh/docs/package.json +2 -2
  20. package/node_modules/@gdh/editor/dist/index.d.ts +101 -0
  21. package/node_modules/@gdh/editor/dist/index.d.ts.map +1 -1
  22. package/node_modules/@gdh/editor/dist/index.js +166 -5
  23. package/node_modules/@gdh/editor/dist/index.js.map +1 -1
  24. package/node_modules/@gdh/editor/package.json +2 -2
  25. package/node_modules/@gdh/mcp/dist/index.d.ts.map +1 -1
  26. package/node_modules/@gdh/mcp/dist/index.js +746 -1
  27. package/node_modules/@gdh/mcp/dist/index.js.map +1 -1
  28. package/node_modules/@gdh/mcp/package.json +8 -8
  29. package/node_modules/@gdh/observability/package.json +2 -2
  30. package/node_modules/@gdh/runtime/dist/bridge-broker.d.ts +9 -1
  31. package/node_modules/@gdh/runtime/dist/bridge-broker.d.ts.map +1 -1
  32. package/node_modules/@gdh/runtime/dist/bridge-broker.js +267 -52
  33. package/node_modules/@gdh/runtime/dist/bridge-broker.js.map +1 -1
  34. package/node_modules/@gdh/runtime/dist/bridge-surface.js +11 -3
  35. package/node_modules/@gdh/runtime/dist/bridge-surface.js.map +1 -1
  36. package/node_modules/@gdh/runtime/package.json +2 -2
  37. package/node_modules/@gdh/scan/package.json +3 -3
  38. package/node_modules/@gdh/verify/package.json +6 -6
  39. package/package.json +12 -12
@@ -428,9 +428,600 @@ const TOOL_MANIFEST = [
428
428
  outputSchema: outputEnvelopeSchema,
429
429
  outputContract: "GdhEditorOperationResult",
430
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: {
670
+ type: "string",
671
+ description: "Required animation key inside the selected library.",
672
+ },
673
+ trackIndex: {
674
+ type: "number",
675
+ description: "Required zero-based track index.",
676
+ },
677
+ mode: {
678
+ type: "string",
679
+ description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
680
+ },
681
+ timeoutMs: {
682
+ type: "number",
683
+ description: "Optional positive timeout in milliseconds for the editor operation.",
684
+ },
685
+ godotEditorBin: {
686
+ type: "string",
687
+ description: "Optional Godot editor executable override for this invocation.",
688
+ },
689
+ }, ["scenePath", "animationPlayerPath", "animationName", "trackIndex"]),
690
+ outputSchema: outputEnvelopeSchema,
691
+ outputContract: "GdhEditorOperationResult",
692
+ },
693
+ {
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.",
696
+ targetPathPolicy: "optional",
697
+ inputSchema: defineObjectSchema("Editor animation keyframe upsert request.", {
698
+ scenePath: {
699
+ type: "string",
700
+ description: "Required res:// path for the saved scene to load.",
701
+ },
702
+ animationPlayerPath: {
703
+ type: "string",
704
+ description: "Required node path to the AnimationPlayer or AnimationMixer.",
705
+ },
706
+ libraryName: {
707
+ type: "string",
708
+ description: "Optional AnimationLibrary name. Defaults to the global empty-name library.",
709
+ },
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.",
730
+ },
731
+ mode: {
732
+ type: "string",
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.",
738
+ },
739
+ godotEditorBin: {
740
+ type: "string",
741
+ description: "Optional Godot editor executable override for this invocation.",
742
+ },
743
+ }, ["scenePath", "animationPlayerPath", "animationName", "trackIndex", "time", "value"]),
744
+ outputSchema: outputEnvelopeSchema,
745
+ outputContract: "GdhEditorOperationResult",
746
+ },
747
+ {
748
+ name: "editor.animation.keyframe.delete",
749
+ summary: "Delete one keyframe from an Animation track by key index or key time.",
750
+ targetPathPolicy: "optional",
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
+ },
780
+ mode: {
781
+ type: "string",
782
+ description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
783
+ },
784
+ timeoutMs: {
785
+ type: "number",
786
+ description: "Optional positive timeout in milliseconds for the editor operation.",
787
+ },
788
+ godotEditorBin: {
789
+ type: "string",
790
+ description: "Optional Godot editor executable override for this invocation.",
791
+ },
792
+ }, ["scenePath", "animationPlayerPath", "animationName", "trackIndex"]),
793
+ outputSchema: outputEnvelopeSchema,
794
+ outputContract: "GdhEditorOperationResult",
795
+ },
796
+ {
797
+ name: "editor.animation.state_machine.create",
798
+ summary: "Create an AnimationNodeStateMachine tree_root on an AnimationTree node through Godot editor APIs.",
799
+ targetPathPolicy: "optional",
800
+ inputSchema: defineObjectSchema("Editor animation state-machine create request.", {
801
+ scenePath: {
802
+ type: "string",
803
+ description: "Required res:// path for the saved scene to load.",
804
+ },
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,
817
+ },
818
+ mode: {
819
+ type: "string",
820
+ description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
821
+ },
822
+ timeoutMs: {
823
+ type: "number",
824
+ description: "Optional positive timeout in milliseconds for the editor operation.",
825
+ },
826
+ godotEditorBin: {
827
+ type: "string",
828
+ description: "Optional Godot editor executable override for this invocation.",
829
+ },
830
+ }, ["scenePath", "animationTreePath"]),
831
+ outputSchema: outputEnvelopeSchema,
832
+ outputContract: "GdhEditorOperationResult",
833
+ },
834
+ {
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.",
837
+ targetPathPolicy: "optional",
838
+ inputSchema: defineObjectSchema("Editor animation state-machine graph read request.", {
839
+ scenePath: {
840
+ type: "string",
841
+ description: "Required res:// path for the saved scene to load.",
842
+ },
843
+ animationTreePath: {
844
+ type: "string",
845
+ description: "Required node path to the AnimationTree with an AnimationNodeStateMachine tree_root.",
846
+ },
847
+ mode: {
848
+ type: "string",
849
+ description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
850
+ },
851
+ timeoutMs: {
852
+ type: "number",
853
+ description: "Optional positive timeout in milliseconds for the editor operation.",
854
+ },
855
+ godotEditorBin: {
856
+ type: "string",
857
+ description: "Optional Godot editor executable override for this invocation.",
858
+ },
859
+ }, ["scenePath", "animationTreePath"]),
860
+ outputSchema: outputEnvelopeSchema,
861
+ outputContract: "GdhEditorOperationResult",
862
+ },
863
+ {
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.",
866
+ targetPathPolicy: "optional",
867
+ inputSchema: defineObjectSchema("Editor animation state-machine node upsert request.", {
868
+ scenePath: {
869
+ type: "string",
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,
893
+ },
894
+ mode: {
895
+ type: "string",
896
+ description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
897
+ },
898
+ timeoutMs: {
899
+ type: "number",
900
+ description: "Optional positive timeout in milliseconds for the editor operation.",
901
+ },
902
+ godotEditorBin: {
903
+ type: "string",
904
+ description: "Optional Godot editor executable override for this invocation.",
905
+ },
906
+ }, ["scenePath", "animationTreePath", "stateName"]),
907
+ outputSchema: outputEnvelopeSchema,
908
+ outputContract: "GdhEditorOperationResult",
909
+ },
910
+ {
911
+ name: "editor.animation.state_machine.node.delete",
912
+ summary: "Delete one node from an AnimationTree state-machine graph.",
913
+ targetPathPolicy: "optional",
914
+ inputSchema: defineObjectSchema("Editor animation state-machine node delete request.", {
915
+ scenePath: {
916
+ type: "string",
917
+ description: "Required res:// path for the saved scene to load.",
918
+ },
919
+ animationTreePath: {
920
+ type: "string",
921
+ description: "Required node path to the AnimationTree.",
922
+ },
923
+ stateName: {
924
+ type: "string",
925
+ description: "Required state-machine node name.",
926
+ },
927
+ mode: {
928
+ type: "string",
929
+ description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
930
+ },
931
+ timeoutMs: {
932
+ type: "number",
933
+ description: "Optional positive timeout in milliseconds for the editor operation.",
934
+ },
935
+ godotEditorBin: {
936
+ type: "string",
937
+ description: "Optional Godot editor executable override for this invocation.",
938
+ },
939
+ }, ["scenePath", "animationTreePath", "stateName"]),
940
+ outputSchema: outputEnvelopeSchema,
941
+ outputContract: "GdhEditorOperationResult",
942
+ },
943
+ {
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.",
946
+ targetPathPolicy: "optional",
947
+ inputSchema: defineObjectSchema("Editor animation state-machine transition upsert request.", {
948
+ scenePath: {
949
+ type: "string",
950
+ description: "Required res:// path for the saved scene to load.",
951
+ },
952
+ animationTreePath: {
953
+ type: "string",
954
+ description: "Required node path to the AnimationTree.",
955
+ },
956
+ fromState: {
957
+ type: "string",
958
+ description: "Required source state name.",
959
+ },
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,
968
+ },
969
+ mode: {
970
+ type: "string",
971
+ description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
972
+ },
973
+ timeoutMs: {
974
+ type: "number",
975
+ description: "Optional positive timeout in milliseconds for the editor operation.",
976
+ },
977
+ godotEditorBin: {
978
+ type: "string",
979
+ description: "Optional Godot editor executable override for this invocation.",
980
+ },
981
+ }, ["scenePath", "animationTreePath", "fromState", "toState"]),
982
+ outputSchema: outputEnvelopeSchema,
983
+ outputContract: "GdhEditorOperationResult",
984
+ },
985
+ {
986
+ name: "editor.animation.state_machine.transition.delete",
987
+ summary: "Delete one transition from an AnimationTree state-machine graph.",
988
+ targetPathPolicy: "optional",
989
+ inputSchema: defineObjectSchema("Editor animation state-machine transition delete request.", {
990
+ scenePath: {
991
+ type: "string",
992
+ description: "Required res:// path for the saved scene to load.",
993
+ },
994
+ animationTreePath: {
995
+ type: "string",
996
+ description: "Required node path to the AnimationTree.",
997
+ },
998
+ fromState: {
999
+ type: "string",
1000
+ description: "Required source state name.",
1001
+ },
1002
+ toState: {
1003
+ type: "string",
1004
+ description: "Required target state name.",
1005
+ },
1006
+ mode: {
1007
+ type: "string",
1008
+ description: "Optional session mode: auto, headless_only, adopt_only, or disabled.",
1009
+ },
1010
+ timeoutMs: {
1011
+ type: "number",
1012
+ description: "Optional positive timeout in milliseconds for the editor operation.",
1013
+ },
1014
+ godotEditorBin: {
1015
+ type: "string",
1016
+ description: "Optional Godot editor executable override for this invocation.",
1017
+ },
1018
+ }, ["scenePath", "animationTreePath", "fromState", "toState"]),
1019
+ outputSchema: outputEnvelopeSchema,
1020
+ outputContract: "GdhEditorOperationResult",
1021
+ },
431
1022
  {
432
1023
  name: "editor.operation.run",
433
- 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.",
434
1025
  targetPathPolicy: "optional",
435
1026
  inputSchema: defineObjectSchema("Editor Bridge operation request.", {
436
1027
  operation: {
@@ -697,6 +1288,129 @@ async function invokeMcpToolWithContext(request, context) {
697
1288
  propertyQuery: readOptionalString(request.input["propertyQuery"], "propertyQuery"),
698
1289
  propertyLimit: readOptionalPositiveInteger(request.input["propertyLimit"], "propertyLimit"),
699
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
+ })));
700
1414
  case "editor.operation.run":
701
1415
  return succeeded(request.toolName, targetPath, await invokeEditorOperationRunTool(targetPath, request.input));
702
1416
  case "bridge.entry.list":
@@ -1083,6 +1797,15 @@ function readOptionalString(value, fieldName) {
1083
1797
  }
1084
1798
  return value;
1085
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
+ }
1086
1809
  function readOptionalEditorSessionMode(value, fieldName) {
1087
1810
  const mode = readOptionalString(value, fieldName);
1088
1811
  if (mode === null || mode === "auto")
@@ -1102,6 +1825,28 @@ function requireString(value, fieldName) {
1102
1825
  }
1103
1826
  return stringValue;
1104
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
+ }
1105
1850
  function requireObject(value, fieldName) {
1106
1851
  if (value === undefined) {
1107
1852
  throw new Error(`MCP input field "${fieldName}" is required.`);