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
@@ -14,11 +14,11 @@ type Entry = {
14
14
  message: string;
15
15
  };
16
16
  export declare class LogTools {
17
- private bridge;
17
+ private _bridge;
18
18
  private env;
19
- private log;
19
+ private _log;
20
20
  private cachedLogPath?;
21
- constructor(bridge: UnrealBridge);
21
+ constructor(_bridge: UnrealBridge);
22
22
  readOutputLog(params: ReadParams): Promise<{
23
23
  success: boolean;
24
24
  error: string;
@@ -3,14 +3,15 @@ import { Logger } from '../utils/logger.js';
3
3
  import { promises as fs } from 'fs';
4
4
  import path from 'path';
5
5
  export class LogTools {
6
- bridge;
6
+ _bridge;
7
7
  env = loadEnv();
8
- log = new Logger('LogTools');
8
+ _log = new Logger('LogTools');
9
9
  cachedLogPath;
10
- constructor(bridge) {
11
- this.bridge = bridge;
10
+ constructor(_bridge) {
11
+ this._bridge = _bridge;
12
12
  }
13
13
  async readOutputLog(params) {
14
+ this._log.debug('Reading output log', { params, connected: this._bridge.isConnected });
14
15
  const target = await this.resolveLogPath(params.logPath);
15
16
  if (!target) {
16
17
  return { success: false, error: 'Log file not found' };
@@ -74,59 +75,6 @@ export class LogTools {
74
75
  if (envLog) {
75
76
  return envLog;
76
77
  }
77
- if (this.bridge.isConnected) {
78
- try {
79
- const script = `
80
- import unreal, json, os
81
- paths = []
82
- try:
83
- d = unreal.Paths.project_log_dir()
84
- if d:
85
- paths.append(os.path.abspath(d))
86
- except Exception:
87
- pass
88
- try:
89
- sd = unreal.Paths.project_saved_dir()
90
- if sd:
91
- p = os.path.join(sd, 'Logs')
92
- paths.append(os.path.abspath(p))
93
- except Exception:
94
- pass
95
- try:
96
- pf = unreal.Paths.get_project_file_path()
97
- if pf:
98
- pd = os.path.dirname(pf)
99
- p = os.path.join(pd, 'Saved', 'Logs')
100
- paths.append(os.path.abspath(p))
101
- except Exception:
102
- pass
103
- all_logs = []
104
- for base in paths:
105
- try:
106
- if os.path.isdir(base):
107
- for name in os.listdir(base):
108
- if name.lower().endswith('.log'):
109
- fp = os.path.join(base, name)
110
- try:
111
- m = os.path.getmtime(fp)
112
- all_logs.append({'p': fp, 'm': m})
113
- except Exception:
114
- pass
115
- except Exception:
116
- pass
117
- all_logs.sort(key=lambda x: x['m'], reverse=True)
118
- print('RESULT:' + json.dumps({'dirs': paths, 'logs': all_logs}))
119
- `.trim();
120
- const res = await this.bridge.executePythonWithResult(script);
121
- const logs = Array.isArray(res?.logs) ? res.logs : [];
122
- for (const entry of logs) {
123
- const p = typeof entry?.p === 'string' ? entry.p : undefined;
124
- if (p && p.trim())
125
- return this.cacheLogPath(p);
126
- }
127
- }
128
- catch { }
129
- }
130
78
  const fallback = await this.findLatestLogInDir(path.join(process.cwd(), 'Saved', 'Logs'));
131
79
  if (fallback) {
132
80
  return fallback;
@@ -1,52 +1,119 @@
1
1
  import { UnrealBridge } from '../unreal-bridge.js';
2
+ import { AutomationBridge } from '../automation/index.js';
2
3
  export declare class MaterialTools {
3
4
  private bridge;
4
- constructor(bridge: UnrealBridge);
5
+ private automationBridge?;
6
+ constructor(bridge: UnrealBridge, automationBridge?: AutomationBridge | undefined);
7
+ setAutomationBridge(automationBridge?: AutomationBridge): void;
5
8
  createMaterial(name: string, path: string): Promise<{
6
- success: boolean;
7
- error: string;
8
- message?: undefined;
9
- path?: undefined;
10
- warnings?: undefined;
11
- details?: undefined;
12
- } | {
13
9
  success: boolean;
14
10
  error: string;
15
11
  message: string;
16
12
  path?: undefined;
17
13
  warnings?: undefined;
18
- details?: undefined;
19
14
  } | {
20
15
  success: boolean;
21
- path: string;
22
- message: string;
23
- error?: undefined;
24
- warnings?: undefined;
25
- details?: undefined;
26
- } | {
27
- success: boolean;
28
- path: string;
29
- message: string;
30
- warnings: string[] | undefined;
31
- details: string[] | undefined;
16
+ path: any;
17
+ message: any;
18
+ warnings: any;
32
19
  error?: undefined;
33
20
  } | {
34
21
  success: boolean;
35
- error: string;
36
- warnings: string[] | undefined;
37
- details: string[] | undefined;
22
+ error: any;
38
23
  message?: undefined;
39
24
  path?: undefined;
25
+ warnings?: undefined;
40
26
  }>;
41
27
  applyMaterialToActor(actorPath: string, materialPath: string, slotIndex?: number): Promise<{
42
28
  success: boolean;
43
29
  message: string;
30
+ transport: any;
31
+ warnings: any[] | undefined;
44
32
  error?: undefined;
33
+ } | {
34
+ success: boolean;
35
+ error: any;
36
+ transport: any;
37
+ message?: undefined;
38
+ warnings?: undefined;
45
39
  } | {
46
40
  success: boolean;
47
41
  error: string;
48
42
  message?: undefined;
43
+ transport?: undefined;
44
+ warnings?: undefined;
49
45
  }>;
50
- private assetExists;
46
+ createMaterialInstance(name: string, path: string, parentMaterial: string, parameters?: Record<string, any>): Promise<any>;
47
+ addNode(params: {
48
+ materialPath: string;
49
+ nodeType: string;
50
+ x: number;
51
+ y: number;
52
+ name?: string;
53
+ timeoutMs?: number;
54
+ }): Promise<import("../automation/types.js").AutomationBridgeResponseMessage | {
55
+ readonly success: false;
56
+ readonly error: "INVALID_MATERIAL_PATH";
57
+ readonly message: "Material path is required";
58
+ } | {
59
+ readonly success: false;
60
+ readonly error: "INVALID_NODE_TYPE";
61
+ readonly message: "Node type is required";
62
+ } | undefined>;
63
+ removeNode(params: {
64
+ materialPath: string;
65
+ nodeId: string;
66
+ timeoutMs?: number;
67
+ }): Promise<import("../automation/types.js").AutomationBridgeResponseMessage | {
68
+ readonly success: false;
69
+ readonly error: "INVALID_MATERIAL_PATH";
70
+ readonly message: "Material path is required";
71
+ } | {
72
+ readonly success: false;
73
+ readonly error: "INVALID_NODE_ID";
74
+ readonly message: "Node ID is required";
75
+ } | undefined>;
76
+ connectNodes(params: {
77
+ materialPath: string;
78
+ sourceNodeId: string;
79
+ targetNodeId: string;
80
+ inputName: string;
81
+ timeoutMs?: number;
82
+ }): Promise<import("../automation/types.js").AutomationBridgeResponseMessage | {
83
+ readonly success: false;
84
+ readonly error: "INVALID_MATERIAL_PATH";
85
+ readonly message: "Material path is required";
86
+ } | {
87
+ readonly success: false;
88
+ readonly error: "INVALID_SOURCE_NODE";
89
+ readonly message: "Source node ID is required";
90
+ } | {
91
+ readonly success: false;
92
+ readonly error: "INVALID_INPUT_NAME";
93
+ readonly message: "Input name is required";
94
+ } | undefined>;
95
+ breakConnections(params: {
96
+ materialPath: string;
97
+ nodeId: string;
98
+ pinName?: string;
99
+ timeoutMs?: number;
100
+ }): Promise<import("../automation/types.js").AutomationBridgeResponseMessage | {
101
+ readonly success: false;
102
+ readonly error: "INVALID_MATERIAL_PATH";
103
+ readonly message: "Material path is required";
104
+ } | {
105
+ readonly success: false;
106
+ readonly error: "INVALID_NODE_ID";
107
+ readonly message: "Node ID is required";
108
+ } | undefined>;
109
+ getNodeDetails(params: {
110
+ materialPath: string;
111
+ nodeId?: string;
112
+ timeoutMs?: number;
113
+ }): Promise<import("../automation/types.js").AutomationBridgeResponseMessage | {
114
+ readonly success: false;
115
+ readonly error: "INVALID_MATERIAL_PATH";
116
+ readonly message: "Material path is required";
117
+ } | undefined>;
51
118
  }
52
119
  //# sourceMappingURL=materials.d.ts.map
@@ -1,29 +1,39 @@
1
- import { coerceBoolean, interpretStandardResult } from '../utils/result-helpers.js';
2
- import { escapePythonString } from '../utils/python.js';
3
1
  export class MaterialTools {
4
2
  bridge;
5
- constructor(bridge) {
3
+ automationBridge;
4
+ constructor(bridge, automationBridge) {
6
5
  this.bridge = bridge;
6
+ this.automationBridge = automationBridge;
7
+ }
8
+ setAutomationBridge(automationBridge) {
9
+ this.automationBridge = automationBridge;
7
10
  }
8
11
  async createMaterial(name, path) {
9
12
  try {
10
- if (!name || name.trim() === '') {
13
+ let effectiveName = name;
14
+ let effectivePath = path;
15
+ if (name && name.includes('/')) {
16
+ const lastSlashIndex = name.lastIndexOf('/');
17
+ effectiveName = name.substring(lastSlashIndex + 1);
18
+ const derivedPath = name.substring(0, lastSlashIndex);
19
+ if (!path || path === '/Game' || path === '') {
20
+ effectivePath = derivedPath;
21
+ }
22
+ }
23
+ if (!effectiveName || effectiveName.trim() === '') {
11
24
  return { success: false, error: 'Material name cannot be empty' };
12
25
  }
13
- if (name.length > 100) {
14
- return { success: false, error: `Material name too long (${name.length} chars). Maximum is 100 characters.` };
26
+ if (effectiveName.length > 100) {
27
+ return { success: false, error: `Material name too long (${effectiveName.length} chars). Maximum is 100 characters.` };
15
28
  }
16
29
  const invalidChars = /[\s./<>|{}[\]()@#\\]/;
17
- if (invalidChars.test(name)) {
18
- const foundChars = name.match(invalidChars);
30
+ if (invalidChars.test(effectiveName)) {
31
+ const foundChars = effectiveName.match(invalidChars);
19
32
  return { success: false, error: `Material name contains invalid characters: '${foundChars?.[0]}'. Avoid spaces, dots, slashes, backslashes, brackets, and special symbols.` };
20
33
  }
21
- if (typeof path !== 'string') {
22
- return { success: false, error: `Invalid path type: expected string, got ${typeof path}` };
23
- }
24
- const trimmedPath = path.trim();
25
- const effectivePath = trimmedPath.length === 0 ? '/Game' : trimmedPath;
26
- const cleanPath = effectivePath.replace(/\/$/, '');
34
+ const trimmedPath = (effectivePath || '').trim();
35
+ const cleanPathStr = trimmedPath.length === 0 ? '/Game' : trimmedPath;
36
+ const cleanPath = cleanPathStr.replace(/\/$/, '');
27
37
  if (!cleanPath.startsWith('/Game') && !cleanPath.startsWith('/Engine')) {
28
38
  return { success: false, error: `Invalid path: must start with /Game or /Engine, got ${cleanPath}` };
29
39
  }
@@ -33,104 +43,36 @@ export class MaterialTools {
33
43
  const errorMessage = `Destination path is read-only and cannot be used for material creation: ${cleanPath}`;
34
44
  return { success: false, error: errorMessage, message: errorMessage };
35
45
  }
36
- const materialPath = `${cleanPath}/${name}`;
37
- const payload = { name, cleanPath, materialPath };
38
- const escapedName = escapePythonString(name);
39
- const pythonCode = `
40
- import unreal, json
41
-
42
- payload = json.loads(r'''${JSON.stringify(payload)}''')
43
- result = {
44
- 'success': False,
45
- 'message': '',
46
- 'error': '',
47
- 'warnings': [],
48
- 'details': [],
49
- 'name': payload.get('name') or "${escapedName}",
50
- 'path': payload.get('materialPath')
51
- }
52
-
53
- material_path = result['path']
54
- clean_path = payload.get('cleanPath') or '/Game'
55
-
56
- try:
57
- if unreal.EditorAssetLibrary.does_asset_exist(material_path):
58
- result['success'] = True
59
- result['exists'] = True
60
- result['message'] = f"Material already exists at {material_path}"
61
- else:
62
- asset_tools = unreal.AssetToolsHelpers.get_asset_tools()
63
- factory = unreal.MaterialFactoryNew()
64
- asset = asset_tools.create_asset(
65
- asset_name=payload.get('name'),
66
- package_path=clean_path,
67
- asset_class=unreal.Material,
68
- factory=factory
69
- )
70
- if asset:
71
- unreal.EditorAssetLibrary.save_asset(material_path)
72
- result['success'] = True
73
- result['created'] = True
74
- result['message'] = f"Material created at {material_path}"
75
- else:
76
- result['error'] = 'Failed to create material'
77
- result['message'] = result['error']
78
- except Exception as exc:
79
- result['error'] = str(exc)
80
- if not result['message']:
81
- result['message'] = result['error']
82
-
83
- print('RESULT:' + json.dumps(result))
84
- `.trim();
85
- const pyResult = await this.bridge.executePython(pythonCode);
86
- const interpreted = interpretStandardResult(pyResult, {
87
- successMessage: `Material ${name} processed`,
88
- failureMessage: 'Failed to create material'
89
- });
90
- if (interpreted.success) {
91
- const exists = coerceBoolean(interpreted.payload.exists, false) === true;
92
- const created = coerceBoolean(interpreted.payload.created, false) === true;
93
- if (exists) {
94
- return { success: true, path: materialPath, message: `Material ${name} already exists at ${materialPath}` };
95
- }
96
- if (created) {
97
- return { success: true, path: materialPath, message: `Material ${name} created at ${materialPath}` };
46
+ const materialPath = `${cleanPath}/${effectiveName}`;
47
+ if (this.automationBridge && typeof this.automationBridge.sendAutomationRequest === 'function') {
48
+ try {
49
+ const resp = await this.automationBridge.sendAutomationRequest('create_material', {
50
+ name: effectiveName,
51
+ destinationPath: cleanPath
52
+ });
53
+ if (resp && resp.success !== false) {
54
+ return {
55
+ success: true,
56
+ path: resp.path || resp.result?.path || materialPath,
57
+ message: resp.message || `Material ${name} created at ${materialPath}`,
58
+ warnings: resp.warnings
59
+ };
60
+ }
61
+ return {
62
+ success: false,
63
+ error: resp?.error ?? resp?.message ?? 'Failed to create material'
64
+ };
98
65
  }
99
- return { success: true, path: materialPath, message: interpreted.message };
100
- }
101
- if (interpreted.error) {
102
- const exists = await this.assetExists(materialPath);
103
- if (exists) {
66
+ catch (err) {
104
67
  return {
105
- success: true,
106
- path: materialPath,
107
- message: `Material ${name} created at ${materialPath}`,
108
- warnings: interpreted.warnings,
109
- details: interpreted.details
68
+ success: false,
69
+ error: `Failed to create material: ${err}`
110
70
  };
111
71
  }
112
- return {
113
- success: false,
114
- error: interpreted.error,
115
- warnings: interpreted.warnings,
116
- details: interpreted.details
117
- };
118
- }
119
- const exists = await this.assetExists(materialPath);
120
- if (exists) {
121
- return {
122
- success: true,
123
- path: materialPath,
124
- message: `Material ${name} created at ${materialPath}`,
125
- warnings: interpreted.warnings,
126
- details: interpreted.details
127
- };
128
72
  }
129
73
  return {
130
74
  success: false,
131
- error: interpreted.message,
132
- warnings: interpreted.warnings,
133
- details: interpreted.details
75
+ error: 'Material creation requires Automation Bridge connection'
134
76
  };
135
77
  }
136
78
  catch (err) {
@@ -139,31 +81,161 @@ print('RESULT:' + json.dumps(result))
139
81
  }
140
82
  async applyMaterialToActor(actorPath, materialPath, slotIndex = 0) {
141
83
  try {
142
- await this.bridge.httpCall('/remote/object/property', 'PUT', {
84
+ const result = await this.bridge.setObjectProperty({
143
85
  objectPath: actorPath,
144
86
  propertyName: `StaticMeshComponent.Materials[${slotIndex}]`,
145
- propertyValue: materialPath
87
+ value: materialPath
146
88
  });
147
- return { success: true, message: 'Material applied' };
89
+ if (result.success) {
90
+ return {
91
+ success: true,
92
+ message: 'Material applied',
93
+ transport: result.transport,
94
+ warnings: Array.isArray(result.warnings) ? result.warnings : undefined
95
+ };
96
+ }
97
+ return {
98
+ success: false,
99
+ error: result.error ?? `Failed to apply material to ${actorPath}`,
100
+ transport: result.transport
101
+ };
148
102
  }
149
103
  catch (err) {
150
104
  return { success: false, error: `Failed to apply material: ${err}` };
151
105
  }
152
106
  }
153
- async assetExists(assetPath) {
107
+ async createMaterialInstance(name, path, parentMaterial, parameters) {
154
108
  try {
155
- const response = await this.bridge.call({
156
- objectPath: '/Script/EditorScriptingUtilities.Default__EditorAssetLibrary',
157
- functionName: 'DoesAssetExist',
158
- parameters: {
159
- AssetPath: assetPath
109
+ if (!name || name.trim() === '') {
110
+ return { success: false, error: 'Material instance name cannot be empty' };
111
+ }
112
+ const cleanPath = (path || '/Game').replace(/\/$/, '');
113
+ if (!cleanPath.startsWith('/Game') && !cleanPath.startsWith('/Engine')) {
114
+ return { success: false, error: `Invalid path: must start with /Game or /Engine, got ${cleanPath}` };
115
+ }
116
+ if (this.automationBridge && typeof this.automationBridge.sendAutomationRequest === 'function') {
117
+ try {
118
+ const resp = await this.automationBridge.sendAutomationRequest('create_material_instance', {
119
+ name,
120
+ destinationPath: cleanPath,
121
+ parentMaterial,
122
+ parameters
123
+ });
124
+ if (resp && resp.success !== false) {
125
+ return { success: true, path: resp.path || resp.result?.path || `${cleanPath}/${name}`, message: resp.message || `Material instance ${name} created at ${cleanPath}/${name}`, warnings: resp.warnings };
126
+ }
127
+ const errTxt = String(resp?.error ?? resp?.message ?? '');
128
+ if (!(errTxt.toLowerCase().includes('unknown') || errTxt.includes('UNKNOWN_PLUGIN_ACTION'))) {
129
+ return { success: false, error: resp?.error ?? resp?.message ?? 'CREATE_MATERIAL_INSTANCE_FAILED' };
130
+ }
160
131
  }
161
- });
162
- return coerceBoolean(response?.ReturnValue ?? response?.Result ?? response, false) === true;
132
+ catch (_e) {
133
+ }
134
+ }
135
+ const createParams = {
136
+ asset_name: name,
137
+ package_path: cleanPath,
138
+ factory_class: 'MaterialInstanceConstantFactoryNew',
139
+ asset_class: 'MaterialInstanceConstant',
140
+ parent_material: parentMaterial,
141
+ parameters: parameters || {}
142
+ };
143
+ try {
144
+ const res = await this.bridge.executeEditorFunction('CREATE_ASSET', createParams);
145
+ if (res && res.success !== false) {
146
+ const createdPath = res.path || res.result?.path || `${cleanPath}/${name}`;
147
+ if (parentMaterial) {
148
+ try {
149
+ await this.bridge.setObjectProperty({ objectPath: createdPath, propertyName: 'parent', value: parentMaterial, markDirty: true });
150
+ }
151
+ catch (_) {
152
+ }
153
+ }
154
+ try {
155
+ await this.bridge.executeEditorFunction('SAVE_ASSET', { path: createdPath });
156
+ }
157
+ catch (_) { }
158
+ return { success: true, path: createdPath, message: `Material instance ${name} created at ${createdPath}` };
159
+ }
160
+ const errTxt = String(res?.error ?? res?.message ?? '');
161
+ if (errTxt.toLowerCase().includes('unknown') || errTxt.includes('UNKNOWN_PLUGIN_ACTION')) {
162
+ return { success: false, error: 'UNKNOWN_PLUGIN_ACTION', message: 'Automation plugin does not implement create_material_instance' };
163
+ }
164
+ return { success: false, error: res?.error ?? res?.message ?? 'CREATE_MATERIAL_INSTANCE_FAILED' };
165
+ }
166
+ catch (err) {
167
+ return { success: false, error: String(err) || 'CREATE_MATERIAL_INSTANCE_FAILED' };
168
+ }
163
169
  }
164
- catch {
165
- return false;
170
+ catch (err) {
171
+ return { success: false, error: `Failed to create material instance: ${err}` };
166
172
  }
167
173
  }
174
+ async addNode(params) {
175
+ if (!params.materialPath)
176
+ return { success: false, error: 'INVALID_MATERIAL_PATH', message: 'Material path is required' };
177
+ if (!params.nodeType)
178
+ return { success: false, error: 'INVALID_NODE_TYPE', message: 'Node type is required' };
179
+ const res = await this.automationBridge?.sendAutomationRequest('manage_material_graph', {
180
+ subAction: 'add_node',
181
+ assetPath: params.materialPath,
182
+ nodeType: params.nodeType,
183
+ x: params.x,
184
+ y: params.y,
185
+ name: params.name
186
+ });
187
+ return res;
188
+ }
189
+ async removeNode(params) {
190
+ if (!params.materialPath)
191
+ return { success: false, error: 'INVALID_MATERIAL_PATH', message: 'Material path is required' };
192
+ if (!params.nodeId)
193
+ return { success: false, error: 'INVALID_NODE_ID', message: 'Node ID is required' };
194
+ const res = await this.automationBridge?.sendAutomationRequest('manage_material_graph', {
195
+ subAction: 'remove_node',
196
+ assetPath: params.materialPath,
197
+ nodeId: params.nodeId
198
+ });
199
+ return res;
200
+ }
201
+ async connectNodes(params) {
202
+ if (!params.materialPath)
203
+ return { success: false, error: 'INVALID_MATERIAL_PATH', message: 'Material path is required' };
204
+ if (!params.sourceNodeId)
205
+ return { success: false, error: 'INVALID_SOURCE_NODE', message: 'Source node ID is required' };
206
+ if (!params.inputName)
207
+ return { success: false, error: 'INVALID_INPUT_NAME', message: 'Input name is required' };
208
+ const res = await this.automationBridge?.sendAutomationRequest('manage_material_graph', {
209
+ subAction: 'connect_nodes',
210
+ assetPath: params.materialPath,
211
+ sourceNodeId: params.sourceNodeId,
212
+ targetNodeId: params.targetNodeId,
213
+ inputName: params.inputName
214
+ });
215
+ return res;
216
+ }
217
+ async breakConnections(params) {
218
+ if (!params.materialPath)
219
+ return { success: false, error: 'INVALID_MATERIAL_PATH', message: 'Material path is required' };
220
+ if (!params.nodeId)
221
+ return { success: false, error: 'INVALID_NODE_ID', message: 'Node ID is required' };
222
+ const res = await this.automationBridge?.sendAutomationRequest('manage_material_graph', {
223
+ subAction: 'break_connections',
224
+ assetPath: params.materialPath,
225
+ nodeId: params.nodeId,
226
+ pinName: params.pinName
227
+ });
228
+ return res;
229
+ }
230
+ async getNodeDetails(params) {
231
+ if (!params.materialPath)
232
+ return { success: false, error: 'INVALID_MATERIAL_PATH', message: 'Material path is required' };
233
+ const res = await this.automationBridge?.sendAutomationRequest('manage_material_graph', {
234
+ subAction: 'get_node_details',
235
+ assetPath: params.materialPath,
236
+ nodeId: params.nodeId
237
+ });
238
+ return res;
239
+ }
168
240
  }
169
241
  //# sourceMappingURL=materials.js.map