unreal-engine-mcp-server 0.4.7 → 0.5.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 (438) hide show
  1. package/.env.example +26 -0
  2. package/.env.production +38 -7
  3. package/.eslintrc.json +0 -54
  4. package/.eslintrc.override.json +8 -0
  5. package/.github/ISSUE_TEMPLATE/bug_report.yml +94 -0
  6. package/.github/ISSUE_TEMPLATE/config.yml +8 -0
  7. package/.github/ISSUE_TEMPLATE/feature_request.yml +56 -0
  8. package/.github/copilot-instructions.md +478 -45
  9. package/.github/dependabot.yml +19 -0
  10. package/.github/labeler.yml +24 -0
  11. package/.github/labels.yml +70 -0
  12. package/.github/pull_request_template.md +42 -0
  13. package/.github/release-drafter.yml +148 -0
  14. package/.github/workflows/auto-merge.yml +38 -0
  15. package/.github/workflows/ci.yml +38 -0
  16. package/.github/workflows/dependency-review.yml +17 -0
  17. package/.github/workflows/gemini-issue-triage.yml +172 -0
  18. package/.github/workflows/greetings.yml +23 -0
  19. package/.github/workflows/labeler.yml +16 -0
  20. package/.github/workflows/links.yml +80 -0
  21. package/.github/workflows/pr-size-labeler.yml +137 -0
  22. package/.github/workflows/publish-mcp.yml +12 -7
  23. package/.github/workflows/release-drafter.yml +23 -0
  24. package/.github/workflows/release.yml +112 -0
  25. package/.github/workflows/semantic-pull-request.yml +35 -0
  26. package/.github/workflows/smoke-test.yml +36 -0
  27. package/.github/workflows/stale.yml +28 -0
  28. package/CHANGELOG.md +267 -31
  29. package/CONTRIBUTING.md +140 -0
  30. package/README.md +166 -71
  31. package/claude_desktop_config_example.json +7 -6
  32. package/dist/automation/bridge.d.ts +50 -0
  33. package/dist/automation/bridge.js +452 -0
  34. package/dist/automation/connection-manager.d.ts +23 -0
  35. package/dist/automation/connection-manager.js +107 -0
  36. package/dist/automation/handshake.d.ts +11 -0
  37. package/dist/automation/handshake.js +89 -0
  38. package/dist/automation/index.d.ts +3 -0
  39. package/dist/automation/index.js +3 -0
  40. package/dist/automation/message-handler.d.ts +12 -0
  41. package/dist/automation/message-handler.js +149 -0
  42. package/dist/automation/request-tracker.d.ts +25 -0
  43. package/dist/automation/request-tracker.js +98 -0
  44. package/dist/automation/types.d.ts +130 -0
  45. package/dist/automation/types.js +2 -0
  46. package/dist/cli.js +32 -5
  47. package/dist/config.d.ts +27 -0
  48. package/dist/config.js +60 -0
  49. package/dist/constants.d.ts +12 -0
  50. package/dist/constants.js +12 -0
  51. package/dist/graphql/resolvers.d.ts +268 -0
  52. package/dist/graphql/resolvers.js +743 -0
  53. package/dist/graphql/schema.d.ts +5 -0
  54. package/dist/graphql/schema.js +437 -0
  55. package/dist/graphql/server.d.ts +26 -0
  56. package/dist/graphql/server.js +115 -0
  57. package/dist/graphql/types.d.ts +7 -0
  58. package/dist/graphql/types.js +2 -0
  59. package/dist/handlers/resource-handlers.d.ts +20 -0
  60. package/dist/handlers/resource-handlers.js +180 -0
  61. package/dist/index.d.ts +31 -18
  62. package/dist/index.js +119 -619
  63. package/dist/prompts/index.js +4 -4
  64. package/dist/resources/actors.d.ts +17 -12
  65. package/dist/resources/actors.js +56 -76
  66. package/dist/resources/assets.d.ts +6 -14
  67. package/dist/resources/assets.js +115 -147
  68. package/dist/resources/levels.d.ts +13 -13
  69. package/dist/resources/levels.js +25 -34
  70. package/dist/server/resource-registry.d.ts +20 -0
  71. package/dist/server/resource-registry.js +37 -0
  72. package/dist/server/tool-registry.d.ts +23 -0
  73. package/dist/server/tool-registry.js +322 -0
  74. package/dist/server-setup.d.ts +21 -0
  75. package/dist/server-setup.js +111 -0
  76. package/dist/services/health-monitor.d.ts +34 -0
  77. package/dist/services/health-monitor.js +105 -0
  78. package/dist/services/metrics-server.d.ts +11 -0
  79. package/dist/services/metrics-server.js +105 -0
  80. package/dist/tools/actors.d.ts +147 -9
  81. package/dist/tools/actors.js +350 -311
  82. package/dist/tools/animation.d.ts +135 -4
  83. package/dist/tools/animation.js +510 -411
  84. package/dist/tools/assets.d.ts +117 -19
  85. package/dist/tools/assets.js +259 -284
  86. package/dist/tools/audio.d.ts +102 -42
  87. package/dist/tools/audio.js +272 -685
  88. package/dist/tools/base-tool.d.ts +17 -0
  89. package/dist/tools/base-tool.js +46 -0
  90. package/dist/tools/behavior-tree.d.ts +94 -0
  91. package/dist/tools/behavior-tree.js +39 -0
  92. package/dist/tools/blueprint/helpers.d.ts +29 -0
  93. package/dist/tools/blueprint/helpers.js +182 -0
  94. package/dist/tools/blueprint.d.ts +228 -118
  95. package/dist/tools/blueprint.js +685 -832
  96. package/dist/tools/consolidated-tool-definitions.d.ts +5462 -1781
  97. package/dist/tools/consolidated-tool-definitions.js +829 -496
  98. package/dist/tools/consolidated-tool-handlers.d.ts +2 -1
  99. package/dist/tools/consolidated-tool-handlers.js +211 -1026
  100. package/dist/tools/debug.d.ts +143 -85
  101. package/dist/tools/debug.js +234 -180
  102. package/dist/tools/dynamic-handler-registry.d.ts +11 -0
  103. package/dist/tools/dynamic-handler-registry.js +101 -0
  104. package/dist/tools/editor.d.ts +139 -18
  105. package/dist/tools/editor.js +239 -244
  106. package/dist/tools/engine.d.ts +10 -4
  107. package/dist/tools/engine.js +13 -5
  108. package/dist/tools/environment.d.ts +36 -0
  109. package/dist/tools/environment.js +267 -0
  110. package/dist/tools/foliage.d.ts +105 -14
  111. package/dist/tools/foliage.js +219 -331
  112. package/dist/tools/handlers/actor-handlers.d.ts +3 -0
  113. package/dist/tools/handlers/actor-handlers.js +232 -0
  114. package/dist/tools/handlers/animation-handlers.d.ts +3 -0
  115. package/dist/tools/handlers/animation-handlers.js +185 -0
  116. package/dist/tools/handlers/argument-helper.d.ts +16 -0
  117. package/dist/tools/handlers/argument-helper.js +80 -0
  118. package/dist/tools/handlers/asset-handlers.d.ts +3 -0
  119. package/dist/tools/handlers/asset-handlers.js +496 -0
  120. package/dist/tools/handlers/audio-handlers.d.ts +3 -0
  121. package/dist/tools/handlers/audio-handlers.js +166 -0
  122. package/dist/tools/handlers/blueprint-handlers.d.ts +4 -0
  123. package/dist/tools/handlers/blueprint-handlers.js +358 -0
  124. package/dist/tools/handlers/common-handlers.d.ts +14 -0
  125. package/dist/tools/handlers/common-handlers.js +56 -0
  126. package/dist/tools/handlers/editor-handlers.d.ts +3 -0
  127. package/dist/tools/handlers/editor-handlers.js +119 -0
  128. package/dist/tools/handlers/effect-handlers.d.ts +3 -0
  129. package/dist/tools/handlers/effect-handlers.js +171 -0
  130. package/dist/tools/handlers/environment-handlers.d.ts +3 -0
  131. package/dist/tools/handlers/environment-handlers.js +170 -0
  132. package/dist/tools/handlers/graph-handlers.d.ts +3 -0
  133. package/dist/tools/handlers/graph-handlers.js +90 -0
  134. package/dist/tools/handlers/input-handlers.d.ts +3 -0
  135. package/dist/tools/handlers/input-handlers.js +21 -0
  136. package/dist/tools/handlers/inspect-handlers.d.ts +3 -0
  137. package/dist/tools/handlers/inspect-handlers.js +383 -0
  138. package/dist/tools/handlers/level-handlers.d.ts +3 -0
  139. package/dist/tools/handlers/level-handlers.js +237 -0
  140. package/dist/tools/handlers/lighting-handlers.d.ts +3 -0
  141. package/dist/tools/handlers/lighting-handlers.js +144 -0
  142. package/dist/tools/handlers/performance-handlers.d.ts +3 -0
  143. package/dist/tools/handlers/performance-handlers.js +130 -0
  144. package/dist/tools/handlers/pipeline-handlers.d.ts +3 -0
  145. package/dist/tools/handlers/pipeline-handlers.js +110 -0
  146. package/dist/tools/handlers/sequence-handlers.d.ts +3 -0
  147. package/dist/tools/handlers/sequence-handlers.js +376 -0
  148. package/dist/tools/handlers/system-handlers.d.ts +4 -0
  149. package/dist/tools/handlers/system-handlers.js +506 -0
  150. package/dist/tools/input.d.ts +19 -0
  151. package/dist/tools/input.js +89 -0
  152. package/dist/tools/introspection.d.ts +103 -40
  153. package/dist/tools/introspection.js +425 -568
  154. package/dist/tools/landscape.d.ts +97 -36
  155. package/dist/tools/landscape.js +280 -409
  156. package/dist/tools/level.d.ts +130 -10
  157. package/dist/tools/level.js +639 -675
  158. package/dist/tools/lighting.d.ts +77 -38
  159. package/dist/tools/lighting.js +441 -943
  160. package/dist/tools/logs.d.ts +3 -3
  161. package/dist/tools/logs.js +5 -57
  162. package/dist/tools/materials.d.ts +91 -24
  163. package/dist/tools/materials.js +190 -118
  164. package/dist/tools/niagara.d.ts +149 -39
  165. package/dist/tools/niagara.js +232 -182
  166. package/dist/tools/performance.d.ts +27 -12
  167. package/dist/tools/performance.js +204 -122
  168. package/dist/tools/physics.d.ts +32 -77
  169. package/dist/tools/physics.js +171 -582
  170. package/dist/tools/property-dictionary.d.ts +13 -0
  171. package/dist/tools/property-dictionary.js +82 -0
  172. package/dist/tools/sequence.d.ts +73 -48
  173. package/dist/tools/sequence.js +196 -748
  174. package/dist/tools/tool-definition-utils.d.ts +59 -0
  175. package/dist/tools/tool-definition-utils.js +35 -0
  176. package/dist/tools/ui.d.ts +66 -34
  177. package/dist/tools/ui.js +134 -214
  178. package/dist/types/env.d.ts +0 -3
  179. package/dist/types/env.js +0 -7
  180. package/dist/types/tool-interfaces.d.ts +898 -0
  181. package/dist/types/tool-interfaces.js +2 -0
  182. package/dist/types/tool-types.d.ts +183 -19
  183. package/dist/types/tool-types.js +0 -4
  184. package/dist/unreal-bridge.d.ts +24 -131
  185. package/dist/unreal-bridge.js +364 -1506
  186. package/dist/utils/command-validator.d.ts +9 -0
  187. package/dist/utils/command-validator.js +67 -0
  188. package/dist/utils/elicitation.d.ts +1 -1
  189. package/dist/utils/elicitation.js +12 -15
  190. package/dist/utils/error-handler.d.ts +2 -51
  191. package/dist/utils/error-handler.js +11 -87
  192. package/dist/utils/ini-reader.d.ts +3 -0
  193. package/dist/utils/ini-reader.js +69 -0
  194. package/dist/utils/logger.js +9 -6
  195. package/dist/utils/normalize.d.ts +3 -0
  196. package/dist/utils/normalize.js +56 -0
  197. package/dist/utils/response-factory.d.ts +7 -0
  198. package/dist/utils/response-factory.js +33 -0
  199. package/dist/utils/response-validator.d.ts +3 -24
  200. package/dist/utils/response-validator.js +130 -81
  201. package/dist/utils/result-helpers.d.ts +4 -5
  202. package/dist/utils/result-helpers.js +15 -16
  203. package/dist/utils/safe-json.js +5 -11
  204. package/dist/utils/unreal-command-queue.d.ts +24 -0
  205. package/dist/utils/unreal-command-queue.js +120 -0
  206. package/dist/utils/validation.d.ts +0 -40
  207. package/dist/utils/validation.js +1 -78
  208. package/dist/wasm/index.d.ts +70 -0
  209. package/dist/wasm/index.js +535 -0
  210. package/docs/GraphQL-API.md +888 -0
  211. package/docs/Migration-Guide-v0.5.0.md +692 -0
  212. package/docs/Roadmap.md +53 -0
  213. package/docs/WebAssembly-Integration.md +628 -0
  214. package/docs/editor-plugin-extension.md +370 -0
  215. package/docs/handler-mapping.md +242 -0
  216. package/docs/native-automation-progress.md +128 -0
  217. package/docs/testing-guide.md +423 -0
  218. package/mcp-config-example.json +6 -6
  219. package/package.json +60 -27
  220. package/plugins/McpAutomationBridge/Config/FilterPlugin.ini +8 -0
  221. package/plugins/McpAutomationBridge/McpAutomationBridge.uplugin +64 -0
  222. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/McpAutomationBridge.Build.cs +189 -0
  223. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.cpp +22 -0
  224. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.h +30 -0
  225. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeHelpers.h +1983 -0
  226. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeModule.cpp +72 -0
  227. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSettings.cpp +46 -0
  228. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSubsystem.cpp +581 -0
  229. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AnimationHandlers.cpp +2394 -0
  230. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetQueryHandlers.cpp +300 -0
  231. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetWorkflowHandlers.cpp +2807 -0
  232. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AudioHandlers.cpp +1087 -0
  233. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BehaviorTreeHandlers.cpp +488 -0
  234. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.cpp +643 -0
  235. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.h +31 -0
  236. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintGraphHandlers.cpp +1184 -0
  237. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers.cpp +5652 -0
  238. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers_List.cpp +152 -0
  239. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ControlHandlers.cpp +2614 -0
  240. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_DebugHandlers.cpp +42 -0
  241. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EditorFunctionHandlers.cpp +1237 -0
  242. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EffectHandlers.cpp +1701 -0
  243. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EnvironmentHandlers.cpp +2145 -0
  244. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_FoliageHandlers.cpp +954 -0
  245. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InputHandlers.cpp +209 -0
  246. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InsightsHandlers.cpp +41 -0
  247. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LandscapeHandlers.cpp +1164 -0
  248. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LevelHandlers.cpp +762 -0
  249. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LightingHandlers.cpp +634 -0
  250. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LogHandlers.cpp +136 -0
  251. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_MaterialGraphHandlers.cpp +494 -0
  252. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraGraphHandlers.cpp +278 -0
  253. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraHandlers.cpp +625 -0
  254. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PerformanceHandlers.cpp +401 -0
  255. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PipelineHandlers.cpp +67 -0
  256. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ProcessRequest.cpp +735 -0
  257. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PropertyHandlers.cpp +2634 -0
  258. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_RenderHandlers.cpp +189 -0
  259. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.cpp +917 -0
  260. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.h +39 -0
  261. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequenceHandlers.cpp +2670 -0
  262. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequencerHandlers.cpp +519 -0
  263. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_TestHandlers.cpp +38 -0
  264. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_UiHandlers.cpp +668 -0
  265. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_WorldPartitionHandlers.cpp +346 -0
  266. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.cpp +1330 -0
  267. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.h +149 -0
  268. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpConnectionManager.cpp +783 -0
  269. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSettings.h +115 -0
  270. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSubsystem.h +796 -0
  271. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpConnectionManager.h +117 -0
  272. package/scripts/check-unreal-connection.mjs +19 -0
  273. package/scripts/clean-tmp.js +23 -0
  274. package/scripts/patch-wasm.js +26 -0
  275. package/scripts/run-all-tests.mjs +131 -0
  276. package/scripts/smoke-test.ts +94 -0
  277. package/scripts/sync-mcp-plugin.js +143 -0
  278. package/scripts/test-no-plugin-alternates.mjs +113 -0
  279. package/scripts/validate-server.js +46 -0
  280. package/scripts/verify-automation-bridge.js +200 -0
  281. package/server.json +57 -21
  282. package/src/automation/bridge.ts +558 -0
  283. package/src/automation/connection-manager.ts +130 -0
  284. package/src/automation/handshake.ts +99 -0
  285. package/src/automation/index.ts +2 -0
  286. package/src/automation/message-handler.ts +167 -0
  287. package/src/automation/request-tracker.ts +123 -0
  288. package/src/automation/types.ts +107 -0
  289. package/src/cli.ts +33 -6
  290. package/src/config.ts +73 -0
  291. package/src/constants.ts +12 -0
  292. package/src/graphql/resolvers.ts +1010 -0
  293. package/src/graphql/schema.ts +452 -0
  294. package/src/graphql/server.ts +154 -0
  295. package/src/graphql/types.ts +7 -0
  296. package/src/handlers/resource-handlers.ts +186 -0
  297. package/src/index.ts +152 -663
  298. package/src/prompts/index.ts +4 -4
  299. package/src/resources/actors.ts +58 -76
  300. package/src/resources/assets.ts +147 -134
  301. package/src/resources/levels.ts +28 -33
  302. package/src/server/resource-registry.ts +47 -0
  303. package/src/server/tool-registry.ts +354 -0
  304. package/src/server-setup.ts +148 -0
  305. package/src/services/health-monitor.ts +132 -0
  306. package/src/services/metrics-server.ts +142 -0
  307. package/src/tools/actors.ts +417 -322
  308. package/src/tools/animation.ts +671 -461
  309. package/src/tools/assets.ts +353 -289
  310. package/src/tools/audio.ts +323 -766
  311. package/src/tools/base-tool.ts +52 -0
  312. package/src/tools/behavior-tree.ts +45 -0
  313. package/src/tools/blueprint/helpers.ts +189 -0
  314. package/src/tools/blueprint.ts +787 -965
  315. package/src/tools/consolidated-tool-definitions.ts +993 -515
  316. package/src/tools/consolidated-tool-handlers.ts +272 -1139
  317. package/src/tools/debug.ts +292 -187
  318. package/src/tools/dynamic-handler-registry.ts +151 -0
  319. package/src/tools/editor.ts +309 -246
  320. package/src/tools/engine.ts +14 -3
  321. package/src/tools/environment.ts +287 -0
  322. package/src/tools/foliage.ts +314 -379
  323. package/src/tools/handlers/actor-handlers.ts +271 -0
  324. package/src/tools/handlers/animation-handlers.ts +237 -0
  325. package/src/tools/handlers/argument-helper.ts +142 -0
  326. package/src/tools/handlers/asset-handlers.ts +532 -0
  327. package/src/tools/handlers/audio-handlers.ts +194 -0
  328. package/src/tools/handlers/blueprint-handlers.ts +380 -0
  329. package/src/tools/handlers/common-handlers.ts +87 -0
  330. package/src/tools/handlers/editor-handlers.ts +123 -0
  331. package/src/tools/handlers/effect-handlers.ts +220 -0
  332. package/src/tools/handlers/environment-handlers.ts +183 -0
  333. package/src/tools/handlers/graph-handlers.ts +116 -0
  334. package/src/tools/handlers/input-handlers.ts +28 -0
  335. package/src/tools/handlers/inspect-handlers.ts +450 -0
  336. package/src/tools/handlers/level-handlers.ts +252 -0
  337. package/src/tools/handlers/lighting-handlers.ts +147 -0
  338. package/src/tools/handlers/performance-handlers.ts +132 -0
  339. package/src/tools/handlers/pipeline-handlers.ts +127 -0
  340. package/src/tools/handlers/sequence-handlers.ts +415 -0
  341. package/src/tools/handlers/system-handlers.ts +564 -0
  342. package/src/tools/input.ts +101 -0
  343. package/src/tools/introspection.ts +493 -584
  344. package/src/tools/landscape.ts +394 -489
  345. package/src/tools/level.ts +752 -694
  346. package/src/tools/lighting.ts +583 -984
  347. package/src/tools/logs.ts +9 -57
  348. package/src/tools/materials.ts +231 -121
  349. package/src/tools/niagara.ts +293 -168
  350. package/src/tools/performance.ts +320 -168
  351. package/src/tools/physics.ts +268 -613
  352. package/src/tools/property-dictionary.ts +98 -0
  353. package/src/tools/sequence.ts +255 -815
  354. package/src/tools/tool-definition-utils.ts +35 -0
  355. package/src/tools/ui.ts +207 -283
  356. package/src/types/env.ts +0 -10
  357. package/src/types/tool-interfaces.ts +250 -0
  358. package/src/types/tool-types.ts +243 -21
  359. package/src/unreal-bridge.ts +460 -1550
  360. package/src/utils/command-validator.ts +75 -0
  361. package/src/utils/elicitation.ts +10 -7
  362. package/src/utils/error-handler.ts +14 -90
  363. package/src/utils/ini-reader.ts +86 -0
  364. package/src/utils/logger.ts +8 -3
  365. package/src/utils/normalize.ts +60 -0
  366. package/src/utils/response-factory.ts +39 -0
  367. package/src/utils/response-validator.ts +176 -56
  368. package/src/utils/result-helpers.ts +21 -19
  369. package/src/utils/safe-json.ts +14 -11
  370. package/src/utils/unreal-command-queue.ts +152 -0
  371. package/src/utils/validation.ts +4 -1
  372. package/src/wasm/index.ts +838 -0
  373. package/test-server.mjs +100 -0
  374. package/tests/run-unreal-tool-tests.mjs +242 -14
  375. package/tests/test-animation.mjs +44 -0
  376. package/tests/test-asset-advanced.mjs +82 -0
  377. package/tests/test-asset-errors.mjs +35 -0
  378. package/tests/test-audio.mjs +219 -0
  379. package/tests/test-automation-timeouts.mjs +98 -0
  380. package/tests/test-behavior-tree.mjs +261 -0
  381. package/tests/test-blueprint-events.mjs +35 -0
  382. package/tests/test-blueprint-graph.mjs +79 -0
  383. package/tests/test-blueprint.mjs +577 -0
  384. package/tests/test-client-mode.mjs +86 -0
  385. package/tests/test-console-command.mjs +56 -0
  386. package/tests/test-control-actor.mjs +425 -0
  387. package/tests/test-control-editor.mjs +80 -0
  388. package/tests/test-extra-tools.mjs +38 -0
  389. package/tests/test-graphql.mjs +322 -0
  390. package/tests/test-inspect.mjs +72 -0
  391. package/tests/test-landscape.mjs +60 -0
  392. package/tests/test-manage-asset.mjs +438 -0
  393. package/tests/test-manage-level.mjs +70 -0
  394. package/tests/test-materials.mjs +356 -0
  395. package/tests/test-niagara.mjs +185 -0
  396. package/tests/test-no-inline-python.mjs +122 -0
  397. package/tests/test-plugin-handshake.mjs +82 -0
  398. package/tests/test-render.mjs +33 -0
  399. package/tests/test-runner.mjs +933 -0
  400. package/tests/test-search-assets.mjs +66 -0
  401. package/tests/test-sequence.mjs +68 -0
  402. package/tests/test-system.mjs +57 -0
  403. package/tests/test-wasm.mjs +193 -0
  404. package/tests/test-world-partition.mjs +215 -0
  405. package/tsconfig.json +3 -3
  406. package/wasm/Cargo.lock +363 -0
  407. package/wasm/Cargo.toml +42 -0
  408. package/wasm/LICENSE +21 -0
  409. package/wasm/README.md +253 -0
  410. package/wasm/src/dependency_resolver.rs +377 -0
  411. package/wasm/src/lib.rs +153 -0
  412. package/wasm/src/property_parser.rs +271 -0
  413. package/wasm/src/transform_math.rs +396 -0
  414. package/wasm/tests/integration.rs +109 -0
  415. package/.github/workflows/smithery-build.yml +0 -29
  416. package/dist/tools/build_environment_advanced.d.ts +0 -65
  417. package/dist/tools/build_environment_advanced.js +0 -633
  418. package/dist/tools/rc.d.ts +0 -110
  419. package/dist/tools/rc.js +0 -437
  420. package/dist/tools/visual.d.ts +0 -40
  421. package/dist/tools/visual.js +0 -282
  422. package/dist/utils/http.d.ts +0 -6
  423. package/dist/utils/http.js +0 -151
  424. package/dist/utils/python-output.d.ts +0 -18
  425. package/dist/utils/python-output.js +0 -290
  426. package/dist/utils/python.d.ts +0 -2
  427. package/dist/utils/python.js +0 -4
  428. package/dist/utils/stdio-redirect.d.ts +0 -2
  429. package/dist/utils/stdio-redirect.js +0 -20
  430. package/docs/unreal-tool-test-cases.md +0 -574
  431. package/smithery.yaml +0 -29
  432. package/src/tools/build_environment_advanced.ts +0 -732
  433. package/src/tools/rc.ts +0 -515
  434. package/src/tools/visual.ts +0 -281
  435. package/src/utils/http.ts +0 -187
  436. package/src/utils/python-output.ts +0 -351
  437. package/src/utils/python.ts +0 -3
  438. package/src/utils/stdio-redirect.ts +0 -18
@@ -0,0 +1,1010 @@
1
+ import type { GraphQLContext } from './types.js';
2
+ import type { UnrealBridge } from '../unreal-bridge.js';
3
+ import { AutomationBridge } from '../automation/index.js';
4
+
5
+ export const scalarResolvers = {
6
+ Vector: {
7
+ serialize: (value: any) => {
8
+ if (!value) return null;
9
+ return typeof value === 'object' && 'x' in value && 'y' in value && 'z' in value
10
+ ? value
11
+ : null;
12
+ },
13
+ parseValue: (value: any) => value,
14
+ parseLiteral: (ast: any) => {
15
+ if (ast.kind === 'ObjectValue') {
16
+ const value: any = {};
17
+ ast.fields.forEach((field: any) => {
18
+ value[field.name.value] = field.value.value;
19
+ });
20
+ return value;
21
+ }
22
+ return null;
23
+ }
24
+ },
25
+ Rotator: {
26
+ serialize: (value: any) => {
27
+ if (!value) return null;
28
+ return typeof value === 'object' && 'pitch' in value && 'yaw' in value && 'roll' in value
29
+ ? value
30
+ : null;
31
+ },
32
+ parseValue: (value: any) => value,
33
+ parseLiteral: (ast: any) => {
34
+ if (ast.kind === 'ObjectValue') {
35
+ const value: any = {};
36
+ ast.fields.forEach((field: any) => {
37
+ value[field.name.value] = field.value.value;
38
+ });
39
+ return value;
40
+ }
41
+ return null;
42
+ }
43
+ },
44
+ Transform: {
45
+ serialize: (value: any) => value,
46
+ parseValue: (value: any) => value,
47
+ parseLiteral: (ast: any) => {
48
+ if (ast.kind === 'ObjectValue') {
49
+ const value: any = {};
50
+ ast.fields.forEach((field: any) => {
51
+ if (field.value.kind === 'ObjectValue') {
52
+ value[field.name.value] = {};
53
+ field.value.fields.forEach((f: any) => {
54
+ value[field.name.value][f.name.value] = f.value.value;
55
+ });
56
+ } else {
57
+ value[field.name.value] = field.value.value;
58
+ }
59
+ });
60
+ return value;
61
+ }
62
+ return null;
63
+ }
64
+ },
65
+ JSON: {
66
+ serialize: (value: any) => value,
67
+ parseValue: (value: any) => value,
68
+ parseLiteral: (ast: any) => {
69
+ switch (ast.kind) {
70
+ case 'StringValue':
71
+ return ast.value;
72
+ case 'BooleanValue':
73
+ return ast.value;
74
+ case 'IntValue':
75
+ case 'FloatValue':
76
+ return Number(ast.value);
77
+ case 'ObjectValue':
78
+ const value: any = {};
79
+ ast.fields.forEach((field: any) => {
80
+ value[field.name.value] = (scalarResolvers as any).JSON.parseLiteral(field.value);
81
+ });
82
+ return value;
83
+ case 'ListValue':
84
+ return ast.values.map((v: any) => (scalarResolvers as any).JSON.parseLiteral(v));
85
+ default:
86
+ return null;
87
+ }
88
+ }
89
+ }
90
+ };
91
+
92
+ interface Asset {
93
+ name: string;
94
+ path: string;
95
+ class: string;
96
+ packagePath: string;
97
+ size?: number;
98
+ metadata?: Record<string, any>;
99
+ tags?: string[];
100
+ }
101
+
102
+ interface Actor {
103
+ name: string;
104
+ class: string;
105
+ location?: { x: number; y: number; z: number };
106
+ rotation?: { pitch: number; yaw: number; roll: number };
107
+ scale?: { x: number; y: number; z: number };
108
+ tags?: string[];
109
+ properties?: Record<string, any>;
110
+ }
111
+
112
+ interface Blueprint {
113
+ name: string;
114
+ path: string;
115
+ parentClass?: string;
116
+ variables?: Array<{
117
+ name: string;
118
+ type: string;
119
+ defaultValue?: any;
120
+ metadata?: Record<string, any>;
121
+ }>;
122
+ functions?: Array<{
123
+ name: string;
124
+ inputs?: Array<{ name: string; type: string }>;
125
+ outputs?: Array<{ name: string; type: string }>;
126
+ }>;
127
+ events?: Array<{ name: string; type: string }>;
128
+ components?: Array<{ name: string; type: string; properties?: Record<string, any> }>;
129
+ scsHierarchy?: Record<string, any>;
130
+ }
131
+
132
+ function logAutomationFailure(source: string, response: any) {
133
+ try {
134
+ if (!response || response.success !== false) {
135
+ return;
136
+ }
137
+ const errorText = (response.error || response.message || '').toString();
138
+ if (errorText.length === 0) {
139
+ return;
140
+ }
141
+ console.error(`[GraphQL] ${source} automation failure:`, errorText);
142
+ } catch {
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Helper to get actor properties from Unreal Bridge
148
+ */
149
+ async function getActorProperties(
150
+ bridge: UnrealBridge,
151
+ actorName: string
152
+ ): Promise<Record<string, any>> {
153
+ try {
154
+ const result = await bridge.getObjectProperty({
155
+ objectPath: actorName,
156
+ propertyName: '*',
157
+ timeoutMs: 5000
158
+ });
159
+ return result.success ? result.value || {} : {};
160
+ } catch (error) {
161
+ console.error('Failed to get actor properties:', error);
162
+ return {};
163
+ }
164
+ }
165
+
166
+ /**
167
+ * Helper to list assets
168
+ */
169
+ async function listAssets(
170
+ automationBridge: AutomationBridge,
171
+ filter?: { class?: string; tag?: string; pathStartsWith?: string },
172
+ pagination?: { offset?: number; limit?: number }
173
+ ): Promise<{ assets: Asset[]; totalCount: number }> {
174
+ try {
175
+ const response = await automationBridge.sendAutomationRequest(
176
+ 'list_assets',
177
+ {
178
+ filter: filter || {},
179
+ pagination: pagination || { offset: 0, limit: 50 }
180
+ },
181
+ { timeoutMs: 30000 }
182
+ );
183
+
184
+ if (response.success && response.result) {
185
+ const result = response.result as any;
186
+ return {
187
+ assets: result.assets || [],
188
+ totalCount: result.totalCount || 0
189
+ };
190
+ }
191
+
192
+ logAutomationFailure('list_assets', response);
193
+ console.error('Failed to list assets:', response);
194
+ return { assets: [], totalCount: 0 };
195
+ } catch (error) {
196
+ console.error('Failed to list assets:', error);
197
+ return { assets: [], totalCount: 0 };
198
+ }
199
+ }
200
+
201
+ /**
202
+ * Helper to list actors
203
+ */
204
+ async function listActors(
205
+ automationBridge: AutomationBridge,
206
+ filter?: { class?: string; tag?: string }
207
+ ): Promise<{ actors: Actor[] }> {
208
+ try {
209
+ const response = await automationBridge.sendAutomationRequest(
210
+ 'list_actors',
211
+ {
212
+ filter: filter || {}
213
+ },
214
+ { timeoutMs: 30000 }
215
+ );
216
+
217
+ if (response.success && response.result) {
218
+ const result = response.result as any;
219
+ return {
220
+ actors: result.actors || []
221
+ };
222
+ }
223
+
224
+ logAutomationFailure('list_actors', response);
225
+ return { actors: [] };
226
+ } catch (error) {
227
+ console.error('Failed to list actors:', error);
228
+ return { actors: [] };
229
+ }
230
+ }
231
+
232
+ /**
233
+ * Helper to get blueprint details
234
+ */
235
+ async function getBlueprint(
236
+ automationBridge: AutomationBridge,
237
+ blueprintPath: string
238
+ ): Promise<Blueprint | null> {
239
+ try {
240
+ const response = await automationBridge.sendAutomationRequest(
241
+ 'get_blueprint',
242
+ {
243
+ blueprintPath
244
+ },
245
+ { timeoutMs: 30000 }
246
+ );
247
+
248
+ if (response.success && response.result) {
249
+ return response.result as Blueprint;
250
+ }
251
+
252
+ logAutomationFailure('get_blueprint', response);
253
+ return null;
254
+ } catch (error) {
255
+ console.error('Failed to get blueprint:', error);
256
+ return null;
257
+ }
258
+ }
259
+
260
+ /**
261
+ * GraphQL Resolvers Implementation
262
+ */
263
+ export const resolvers = {
264
+ // Query resolvers
265
+ Query: {
266
+ assets: async (_: any, args: any, context: GraphQLContext) => {
267
+ const { filter, pagination } = args;
268
+ const { assets, totalCount } = await listAssets(
269
+ context.automationBridge,
270
+ filter,
271
+ pagination
272
+ );
273
+
274
+ // Convert to connection format for pagination
275
+ const edges = assets.map((asset, index) => ({
276
+ node: asset,
277
+ cursor: Buffer.from(`${asset.path}:${index}`).toString('base64')
278
+ }));
279
+
280
+ return {
281
+ edges,
282
+ pageInfo: {
283
+ hasNextPage: (pagination?.offset || 0) + assets.length < totalCount,
284
+ hasPreviousPage: (pagination?.offset || 0) > 0,
285
+ startCursor: edges.length > 0 ? edges[0].cursor : null,
286
+ endCursor: edges.length > 0 ? edges[edges.length - 1].cursor : null
287
+ },
288
+ totalCount
289
+ };
290
+ },
291
+
292
+ asset: async (_: any, { path }: { path: string }, context: GraphQLContext) => {
293
+ try {
294
+ const response = await context.automationBridge.sendAutomationRequest(
295
+ 'get_asset',
296
+ { assetPath: path },
297
+ { timeoutMs: 10000 }
298
+ );
299
+
300
+ if (response.success && response.result) {
301
+ return response.result;
302
+ }
303
+
304
+ return null;
305
+ } catch (error) {
306
+ console.error('Failed to get asset:', error);
307
+ return null;
308
+ }
309
+ },
310
+
311
+ actors: async (_: any, args: any, context: GraphQLContext) => {
312
+ const { filter, pagination } = args;
313
+ const { actors } = await listActors(context.automationBridge, filter);
314
+
315
+ const offset = pagination?.offset ?? 0;
316
+ const limit = pagination?.limit ?? 50;
317
+
318
+ const paginatedActors = actors.slice(offset, offset + limit);
319
+
320
+ const edges = paginatedActors.map((actor, index) => ({
321
+ node: actor,
322
+ cursor: Buffer.from(`${actor.name}:${offset + index}`).toString('base64')
323
+ }));
324
+
325
+ return {
326
+ edges,
327
+ pageInfo: {
328
+ hasNextPage: offset + paginatedActors.length < actors.length,
329
+ hasPreviousPage: offset > 0,
330
+ startCursor: edges.length > 0 ? edges[0].cursor : null,
331
+ endCursor: edges.length > 0 ? edges[edges.length - 1].cursor : null
332
+ },
333
+ totalCount: actors.length
334
+ };
335
+ },
336
+
337
+ actor: async (_: any, { name }: { name: string }, context: GraphQLContext) => {
338
+ try {
339
+ const actors = await listActors(context.automationBridge, { tag: name });
340
+ if (actors.actors.length > 0) {
341
+ return actors.actors[0];
342
+ }
343
+ return null;
344
+ } catch (error) {
345
+ console.error('Failed to get actor:', error);
346
+ return null;
347
+ }
348
+ },
349
+
350
+ blueprints: async (_: any, args: any, context: GraphQLContext) => {
351
+ const { filter, pagination } = args;
352
+ try {
353
+ const response = await context.automationBridge.sendAutomationRequest(
354
+ 'list_blueprints',
355
+ {
356
+ filter: filter || {},
357
+ pagination: pagination || { offset: 0, limit: 50 }
358
+ },
359
+ { timeoutMs: 30000 }
360
+ );
361
+
362
+ const blueprints: Blueprint[] = response.success && response.result
363
+ ? (response.result as any).blueprints || []
364
+ : [];
365
+
366
+ const edges = blueprints.map((blueprint, index) => ({
367
+ node: blueprint,
368
+ cursor: Buffer.from(`${blueprint.path}:${index}`).toString('base64')
369
+ }));
370
+
371
+ return {
372
+ edges,
373
+ pageInfo: {
374
+ hasNextPage: (pagination?.offset || 0) + blueprints.length < (response.result as any)?.totalCount || 0,
375
+ hasPreviousPage: (pagination?.offset || 0) > 0,
376
+ startCursor: edges.length > 0 ? edges[0].cursor : null,
377
+ endCursor: edges.length > 0 ? edges[edges.length - 1].cursor : null
378
+ },
379
+ totalCount: blueprints.length
380
+ };
381
+ } catch (error) {
382
+ console.error('Failed to list blueprints:', error);
383
+ return {
384
+ edges: [],
385
+ pageInfo: {
386
+ hasNextPage: false,
387
+ hasPreviousPage: false,
388
+ startCursor: null,
389
+ endCursor: null
390
+ },
391
+ totalCount: 0
392
+ };
393
+ }
394
+ },
395
+
396
+ blueprint: async (_: any, { path }: { path: string }, context: GraphQLContext) => {
397
+ return await getBlueprint(context.automationBridge, path);
398
+ },
399
+
400
+ levels: async (_: any, __: any, context: GraphQLContext) => {
401
+ try {
402
+ const response = await context.automationBridge.sendAutomationRequest(
403
+ 'list_levels',
404
+ {},
405
+ { timeoutMs: 10000 }
406
+ );
407
+
408
+ if (response.success && response.result) {
409
+ return (response.result as any).levels || [];
410
+ }
411
+
412
+ return [];
413
+ } catch (error) {
414
+ console.error('Failed to list levels:', error);
415
+ return [];
416
+ }
417
+ },
418
+
419
+ currentLevel: async (_: any, __: any, context: GraphQLContext) => {
420
+ try {
421
+ const response = await context.automationBridge.sendAutomationRequest(
422
+ 'get_current_level',
423
+ {},
424
+ { timeoutMs: 10000 }
425
+ );
426
+
427
+ if (response.success && response.result) {
428
+ return response.result;
429
+ }
430
+
431
+ return null;
432
+ } catch (error) {
433
+ console.error('Failed to get current level:', error);
434
+ return null;
435
+ }
436
+ },
437
+
438
+ materials: async (_: any, args: any, context: GraphQLContext) => {
439
+ const { filter, pagination } = args;
440
+ try {
441
+ const materialFilter = { ...filter, class: 'MaterialInterface' };
442
+ const { assets, totalCount } = await listAssets(
443
+ context.automationBridge,
444
+ materialFilter,
445
+ pagination
446
+ );
447
+
448
+ const offset = pagination?.offset ?? 0;
449
+ const edges = assets.map((material, index) => ({
450
+ node: material, // Material type in schema matches Asset mostly
451
+ cursor: Buffer.from(`${material.path}:${offset + index}`).toString('base64')
452
+ }));
453
+
454
+ return {
455
+ edges,
456
+ pageInfo: {
457
+ hasNextPage: (pagination?.offset || 0) + assets.length < totalCount,
458
+ hasPreviousPage: (pagination?.offset || 0) > 0,
459
+ startCursor: edges.length > 0 ? edges[0].cursor : null,
460
+ endCursor: edges.length > 0 ? edges[edges.length - 1].cursor : null
461
+ },
462
+ totalCount
463
+ };
464
+ } catch (error) {
465
+ console.error('Failed to list materials:', error);
466
+ return {
467
+ edges: [],
468
+ pageInfo: {
469
+ hasNextPage: false,
470
+ hasPreviousPage: false,
471
+ startCursor: null,
472
+ endCursor: null
473
+ },
474
+ totalCount: 0
475
+ };
476
+ }
477
+ },
478
+
479
+ sequences: async (_: any, args: any, context: GraphQLContext) => {
480
+ const { filter, pagination } = args;
481
+ try {
482
+ const sequenceFilter = { ...filter, class: 'LevelSequence' };
483
+ const { assets, totalCount } = await listAssets(
484
+ context.automationBridge,
485
+ sequenceFilter,
486
+ pagination
487
+ );
488
+
489
+ const offset = pagination?.offset ?? 0;
490
+ const edges = assets.map((sequence, index) => ({
491
+ node: sequence,
492
+ cursor: Buffer.from(`${sequence.path}:${offset + index}`).toString('base64')
493
+ }));
494
+
495
+ return {
496
+ edges,
497
+ pageInfo: {
498
+ hasNextPage: (pagination?.offset || 0) + assets.length < totalCount,
499
+ hasPreviousPage: (pagination?.offset || 0) > 0,
500
+ startCursor: edges.length > 0 ? edges[0].cursor : null,
501
+ endCursor: edges.length > 0 ? edges[edges.length - 1].cursor : null
502
+ },
503
+ totalCount
504
+ };
505
+ } catch (error) {
506
+ console.error('Failed to list sequences:', error);
507
+ return {
508
+ edges: [],
509
+ pageInfo: {
510
+ hasNextPage: false,
511
+ hasPreviousPage: false,
512
+ startCursor: null,
513
+ endCursor: null
514
+ },
515
+ totalCount: 0
516
+ };
517
+ }
518
+ },
519
+
520
+ worldPartitionCells: async (_: any, __: any, context: GraphQLContext) => {
521
+ try {
522
+ const response = await context.automationBridge.sendAutomationRequest(
523
+ 'manage_world_partition',
524
+ { subAction: 'get_cells' },
525
+ { timeoutMs: 10000 }
526
+ );
527
+
528
+ if (response.success && response.result) {
529
+ return (response.result as any).cells || [];
530
+ }
531
+ return [];
532
+ } catch (error) {
533
+ console.error('Failed to list world partition cells:', error);
534
+ return [];
535
+ }
536
+ },
537
+
538
+ niagaraSystems: async (_: any, args: any, context: GraphQLContext) => {
539
+ const { filter, pagination } = args;
540
+ try {
541
+ // Re-use list_assets with filter for NiagaraSystem class
542
+ const niagaraFilter = { ...filter, class: 'NiagaraSystem' };
543
+ const { assets, totalCount } = await listAssets(
544
+ context.automationBridge,
545
+ niagaraFilter,
546
+ pagination
547
+ );
548
+
549
+ const offset = pagination?.offset ?? 0;
550
+ const edges = assets.map((asset, index) => ({
551
+ node: {
552
+ ...asset,
553
+ emitters: [],
554
+ parameters: []
555
+ },
556
+ cursor: Buffer.from(`${asset.path}:${offset + index}`).toString('base64')
557
+ }));
558
+
559
+ return {
560
+ edges,
561
+ pageInfo: {
562
+ hasNextPage: (pagination?.offset || 0) + assets.length < totalCount,
563
+ hasPreviousPage: (pagination?.offset || 0) > 0,
564
+ startCursor: edges.length > 0 ? edges[0].cursor : null,
565
+ endCursor: edges.length > 0 ? edges[edges.length - 1].cursor : null
566
+ },
567
+ totalCount
568
+ };
569
+ } catch (error) {
570
+ console.error('Failed to list niagara systems:', error);
571
+ return {
572
+ edges: [],
573
+ pageInfo: {
574
+ hasNextPage: false,
575
+ hasPreviousPage: false,
576
+ startCursor: null,
577
+ endCursor: null
578
+ },
579
+ totalCount: 0
580
+ };
581
+ }
582
+ },
583
+
584
+ niagaraSystem: async (_: any, { path }: { path: string }, context: GraphQLContext) => {
585
+ try {
586
+ // Check if it's a niagara system
587
+ const asset = await context.automationBridge.sendAutomationRequest(
588
+ 'get_asset',
589
+ { assetPath: path },
590
+ { timeoutMs: 10000 }
591
+ );
592
+ if (asset.success && asset.result && (asset.result as any).class === 'NiagaraSystem') {
593
+ return {
594
+ ...(asset.result as any),
595
+ emitters: [],
596
+ parameters: []
597
+ };
598
+ }
599
+ return null;
600
+ } catch (error) {
601
+ console.error('Failed to get niagara system:', error);
602
+ return null;
603
+ }
604
+ },
605
+
606
+ search: async (_: any, { query, type }: any, context: GraphQLContext) => {
607
+ try {
608
+ const response = await context.automationBridge.sendAutomationRequest(
609
+ 'search',
610
+ {
611
+ query,
612
+ type: type || 'ALL'
613
+ },
614
+ { timeoutMs: 30000 }
615
+ );
616
+
617
+ if (response.success && response.result) {
618
+ return (response.result as any).results || [];
619
+ }
620
+
621
+ return [];
622
+ } catch (error) {
623
+ console.error('Failed to search:', error);
624
+ return [];
625
+ }
626
+ }
627
+ },
628
+
629
+ // Mutation resolvers
630
+ Mutation: {
631
+ duplicateAsset: async (_: any, { path, newName }: any, context: GraphQLContext) => {
632
+ try {
633
+ const response = await context.automationBridge.sendAutomationRequest(
634
+ 'duplicate_asset',
635
+ {
636
+ assetPath: path,
637
+ newName
638
+ },
639
+ { timeoutMs: 60000 }
640
+ );
641
+
642
+ if (response.success && response.result) {
643
+ return response.result;
644
+ }
645
+
646
+ throw new Error(response.error || 'Failed to duplicate asset');
647
+ } catch (error) {
648
+ console.error('Failed to duplicate asset:', error);
649
+ throw error;
650
+ }
651
+ },
652
+
653
+ moveAsset: async (_: any, { path, newPath }: any, context: GraphQLContext) => {
654
+ try {
655
+ const response = await context.automationBridge.sendAutomationRequest(
656
+ 'move_asset',
657
+ {
658
+ assetPath: path,
659
+ destinationPath: newPath
660
+ },
661
+ { timeoutMs: 60000 }
662
+ );
663
+
664
+ if (response.success && response.result) {
665
+ return response.result;
666
+ }
667
+
668
+ throw new Error(response.error || 'Failed to move asset');
669
+ } catch (error) {
670
+ console.error('Failed to move asset:', error);
671
+ throw error;
672
+ }
673
+ },
674
+
675
+ deleteAsset: async (_: any, { path }: { path: string }, context: GraphQLContext) => {
676
+ try {
677
+ const response = await context.automationBridge.sendAutomationRequest(
678
+ 'delete_asset',
679
+ {
680
+ assetPath: path
681
+ },
682
+ { timeoutMs: 30000 }
683
+ );
684
+
685
+ return response.success || false;
686
+ } catch (error) {
687
+ console.error('Failed to delete asset:', error);
688
+ return false;
689
+ }
690
+ },
691
+
692
+ spawnActor: async (_: any, { input }: any, context: GraphQLContext) => {
693
+ try {
694
+ const response = await context.automationBridge.sendAutomationRequest(
695
+ 'spawn_actor',
696
+ input,
697
+ { timeoutMs: 10000 }
698
+ );
699
+
700
+ if (response.success && response.result) {
701
+ return response.result;
702
+ }
703
+
704
+ throw new Error(response.error || 'Failed to spawn actor');
705
+ } catch (error) {
706
+ console.error('Failed to spawn actor:', error);
707
+ throw error;
708
+ }
709
+ },
710
+
711
+ deleteActor: async (_: any, { name }: { name: string }, context: GraphQLContext) => {
712
+ try {
713
+ const response = await context.automationBridge.sendAutomationRequest(
714
+ 'delete_actor',
715
+ {
716
+ actorName: name
717
+ },
718
+ { timeoutMs: 10000 }
719
+ );
720
+
721
+ return response.success || false;
722
+ } catch (error) {
723
+ console.error('Failed to delete actor:', error);
724
+ return false;
725
+ }
726
+ },
727
+
728
+ setActorTransform: async (_: any, { name, transform }: any, context: GraphQLContext) => {
729
+ try {
730
+ const response = await context.automationBridge.sendAutomationRequest(
731
+ 'set_actor_transform',
732
+ {
733
+ actorName: name,
734
+ transform
735
+ },
736
+ { timeoutMs: 10000 }
737
+ );
738
+
739
+ if (response.success && response.result) {
740
+ return response.result;
741
+ }
742
+
743
+ throw new Error(response.error || 'Failed to set actor transform');
744
+ } catch (error) {
745
+ console.error('Failed to set actor transform:', error);
746
+ throw error;
747
+ }
748
+ },
749
+
750
+ createBlueprint: async (_: any, { input }: any, context: GraphQLContext) => {
751
+ try {
752
+ const response = await context.automationBridge.sendAutomationRequest(
753
+ 'create_blueprint',
754
+ input,
755
+ { timeoutMs: 60000 }
756
+ );
757
+
758
+ if (response.success && response.result) {
759
+ return response.result;
760
+ }
761
+
762
+ throw new Error(response.error || 'Failed to create blueprint');
763
+ } catch (error) {
764
+ console.error('Failed to create blueprint:', error);
765
+ throw error;
766
+ }
767
+ },
768
+
769
+ addVariableToBlueprint: async (_: any, { path, input }: any, context: GraphQLContext) => {
770
+ try {
771
+ const response = await context.automationBridge.sendAutomationRequest(
772
+ 'add_variable_to_blueprint',
773
+ {
774
+ blueprintPath: path,
775
+ ...input
776
+ },
777
+ { timeoutMs: 30000 }
778
+ );
779
+
780
+ if (response.success && response.result) {
781
+ return response.result;
782
+ }
783
+
784
+ throw new Error(response.error || 'Failed to add variable to blueprint');
785
+ } catch (error) {
786
+ console.error('Failed to add variable to blueprint:', error);
787
+ throw error;
788
+ }
789
+ },
790
+
791
+ addFunctionToBlueprint: async (_: any, { path, input }: any, context: GraphQLContext) => {
792
+ try {
793
+ const response = await context.automationBridge.sendAutomationRequest(
794
+ 'add_function_to_blueprint',
795
+ {
796
+ blueprintPath: path,
797
+ ...input
798
+ },
799
+ { timeoutMs: 30000 }
800
+ );
801
+
802
+ if (response.success && response.result) {
803
+ return response.result;
804
+ }
805
+
806
+ throw new Error(response.error || 'Failed to add function to blueprint');
807
+ } catch (error) {
808
+ console.error('Failed to add function to blueprint:', error);
809
+ throw error;
810
+ }
811
+ },
812
+
813
+ loadLevel: async (_: any, { path }: { path: string }, context: GraphQLContext) => {
814
+ try {
815
+ const response = await context.automationBridge.sendAutomationRequest(
816
+ 'load_level',
817
+ {
818
+ levelPath: path
819
+ },
820
+ { timeoutMs: 30000 }
821
+ );
822
+
823
+ if (response.success && response.result) {
824
+ return response.result;
825
+ }
826
+
827
+ throw new Error(response.error || 'Failed to load level');
828
+ } catch (error) {
829
+ console.error('Failed to load level:', error);
830
+ throw error;
831
+ }
832
+ },
833
+
834
+ saveLevel: async (_: any, { path }: { path?: string }, context: GraphQLContext) => {
835
+ try {
836
+ const response = await context.automationBridge.sendAutomationRequest(
837
+ 'save_level',
838
+ {
839
+ levelPath: path
840
+ },
841
+ { timeoutMs: 30000 }
842
+ );
843
+
844
+ return response.success || false;
845
+ } catch (error) {
846
+ console.error('Failed to save level:', error);
847
+ return false;
848
+ }
849
+ },
850
+
851
+ createMaterialInstance: async (_: any, { parentPath, name, parameters }: any, context: GraphQLContext) => {
852
+ try {
853
+ const response = await context.automationBridge.sendAutomationRequest(
854
+ 'create_material_instance',
855
+ {
856
+ parentMaterialPath: parentPath,
857
+ instanceName: name,
858
+ parameters: parameters || {}
859
+ },
860
+ { timeoutMs: 30000 }
861
+ );
862
+
863
+ if (response.success && response.result) {
864
+ return response.result;
865
+ }
866
+
867
+ throw new Error(response.error || 'Failed to create material instance');
868
+ } catch (error) {
869
+ console.error('Failed to create material instance:', error);
870
+ throw error;
871
+ }
872
+ }
873
+ },
874
+
875
+ // Field resolvers
876
+ Asset: {
877
+ dependencies: async (parent: Asset, _: any, context: GraphQLContext) => {
878
+ try {
879
+ const response = await context.automationBridge.sendAutomationRequest(
880
+ 'get_asset_dependencies',
881
+ {
882
+ assetPath: parent.path
883
+ },
884
+ { timeoutMs: 10000 }
885
+ );
886
+
887
+ if (response.success && response.result) {
888
+ return (response.result as any).dependencies || [];
889
+ }
890
+
891
+ return [];
892
+ } catch (error) {
893
+ console.error('Failed to get asset dependencies:', error);
894
+ return [];
895
+ }
896
+ },
897
+
898
+ dependents: async (parent: Asset, _: any, context: GraphQLContext) => {
899
+ try {
900
+ const response = await context.automationBridge.sendAutomationRequest(
901
+ 'get_asset_dependents',
902
+ {
903
+ assetPath: parent.path
904
+ },
905
+ { timeoutMs: 10000 }
906
+ );
907
+
908
+ if (response.success && response.result) {
909
+ return (response.result as any).dependents || [];
910
+ }
911
+
912
+ return [];
913
+ } catch (error) {
914
+ console.error('Failed to get asset dependents:', error);
915
+ return [];
916
+ }
917
+ }
918
+ },
919
+
920
+ Actor: {
921
+ properties: async (parent: Actor, _: any, context: GraphQLContext) => {
922
+ return await getActorProperties(context.bridge, parent.name);
923
+ },
924
+
925
+ components: async (parent: Actor, _: any, context: GraphQLContext) => {
926
+ try {
927
+ const response = await context.automationBridge.sendAutomationRequest(
928
+ 'get_actor_components',
929
+ {
930
+ actorName: parent.name
931
+ },
932
+ { timeoutMs: 10000 }
933
+ );
934
+
935
+ if (response.success && response.result) {
936
+ return (response.result as any).components || [];
937
+ }
938
+
939
+ return [];
940
+ } catch (error) {
941
+ console.error('Failed to get actor components:', error);
942
+ return [];
943
+ }
944
+ }
945
+ },
946
+
947
+ Blueprint: {
948
+ variables: async (parent: Blueprint, _args: any, _context: GraphQLContext) => {
949
+ return parent.variables || [];
950
+ },
951
+
952
+ functions: async (parent: Blueprint, _args: any, _context: GraphQLContext) => {
953
+ return parent.functions || [];
954
+ },
955
+
956
+ events: async (parent: Blueprint, _args: any, _context: GraphQLContext) => {
957
+ return parent.events || [];
958
+ },
959
+
960
+ components: async (parent: Blueprint, _args: any, _context: GraphQLContext) => {
961
+ return parent.components || [];
962
+ }
963
+ },
964
+
965
+ Material: {
966
+ parameters: async (parent: any, _: any, context: GraphQLContext) => {
967
+ try {
968
+ const response = await context.automationBridge.sendAutomationRequest(
969
+ 'get_material_parameters',
970
+ {
971
+ materialPath: parent.path
972
+ },
973
+ { timeoutMs: 10000 }
974
+ );
975
+
976
+ if (response.success && response.result) {
977
+ return (response.result as any).parameters || [];
978
+ }
979
+
980
+ return [];
981
+ } catch (error) {
982
+ console.error('Failed to get material parameters:', error);
983
+ return [];
984
+ }
985
+ }
986
+ },
987
+
988
+ Sequence: {
989
+ tracks: async (parent: any, _: any, context: GraphQLContext) => {
990
+ try {
991
+ const response = await context.automationBridge.sendAutomationRequest(
992
+ 'get_sequence_tracks',
993
+ {
994
+ sequencePath: parent.path
995
+ },
996
+ { timeoutMs: 10000 }
997
+ );
998
+
999
+ if (response.success && response.result) {
1000
+ return (response.result as any).tracks || [];
1001
+ }
1002
+
1003
+ return [];
1004
+ } catch (error) {
1005
+ console.error('Failed to get sequence tracks:', error);
1006
+ return [];
1007
+ }
1008
+ }
1009
+ }
1010
+ };