unreal-engine-mcp-server 0.5.3 → 0.5.5

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 (480) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/dist/automation/bridge.d.ts +1 -0
  3. package/dist/automation/bridge.d.ts.map +1 -0
  4. package/dist/automation/bridge.js +62 -4
  5. package/dist/automation/bridge.js.map +1 -0
  6. package/dist/automation/connection-manager.d.ts.map +1 -0
  7. package/dist/automation/connection-manager.js.map +1 -0
  8. package/dist/automation/handshake.d.ts.map +1 -0
  9. package/dist/automation/handshake.js.map +1 -0
  10. package/dist/automation/index.d.ts.map +1 -0
  11. package/dist/automation/index.js.map +1 -0
  12. package/dist/automation/message-handler.d.ts.map +1 -0
  13. package/dist/automation/message-handler.js.map +1 -0
  14. package/dist/automation/request-tracker.d.ts.map +1 -0
  15. package/dist/automation/request-tracker.js.map +1 -0
  16. package/dist/automation/types.d.ts +1 -0
  17. package/dist/automation/types.d.ts.map +1 -0
  18. package/dist/automation/types.js.map +1 -0
  19. package/dist/cli.d.ts.map +1 -0
  20. package/dist/cli.js +4 -3
  21. package/dist/cli.js.map +1 -0
  22. package/dist/config/class-aliases.d.ts.map +1 -0
  23. package/dist/config/class-aliases.js.map +1 -0
  24. package/dist/config.d.ts.map +1 -0
  25. package/dist/config.js.map +1 -0
  26. package/dist/constants.d.ts +2 -0
  27. package/dist/constants.d.ts.map +1 -0
  28. package/dist/constants.js +2 -0
  29. package/dist/constants.js.map +1 -0
  30. package/dist/graphql/loaders.d.ts.map +1 -0
  31. package/dist/graphql/loaders.js.map +1 -0
  32. package/dist/graphql/resolvers.d.ts.map +1 -0
  33. package/dist/graphql/resolvers.js +29 -29
  34. package/dist/graphql/resolvers.js.map +1 -0
  35. package/dist/graphql/schema.d.ts.map +1 -0
  36. package/dist/graphql/schema.js.map +1 -0
  37. package/dist/graphql/server.d.ts +0 -1
  38. package/dist/graphql/server.d.ts.map +1 -0
  39. package/dist/graphql/server.js +15 -16
  40. package/dist/graphql/server.js.map +1 -0
  41. package/dist/graphql/types.d.ts.map +1 -0
  42. package/dist/graphql/types.js.map +1 -0
  43. package/dist/handlers/resource-handlers.d.ts.map +1 -0
  44. package/dist/handlers/resource-handlers.js.map +1 -0
  45. package/dist/index.d.ts +1 -0
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +64 -7
  48. package/dist/index.js.map +1 -0
  49. package/dist/resources/actors.d.ts.map +1 -0
  50. package/dist/resources/actors.js.map +1 -0
  51. package/dist/resources/assets.d.ts.map +1 -0
  52. package/dist/resources/assets.js +6 -4
  53. package/dist/resources/assets.js.map +1 -0
  54. package/dist/resources/levels.d.ts.map +1 -0
  55. package/dist/resources/levels.js.map +1 -0
  56. package/dist/server/resource-registry.d.ts.map +1 -0
  57. package/dist/server/resource-registry.js.map +1 -0
  58. package/dist/server/tool-registry.d.ts.map +1 -0
  59. package/dist/server/tool-registry.js.map +1 -0
  60. package/dist/server-setup.d.ts.map +1 -0
  61. package/dist/server-setup.js.map +1 -0
  62. package/dist/services/health-monitor.d.ts.map +1 -0
  63. package/dist/services/health-monitor.js.map +1 -0
  64. package/dist/services/metrics-server.d.ts.map +1 -0
  65. package/dist/services/metrics-server.js +3 -3
  66. package/dist/services/metrics-server.js.map +1 -0
  67. package/dist/tools/actors.d.ts.map +1 -0
  68. package/dist/tools/actors.js +3 -1
  69. package/dist/tools/actors.js.map +1 -0
  70. package/dist/tools/animation.d.ts.map +1 -0
  71. package/dist/tools/animation.js +2 -2
  72. package/dist/tools/animation.js.map +1 -0
  73. package/dist/tools/assets.d.ts.map +1 -0
  74. package/dist/tools/assets.js.map +1 -0
  75. package/dist/tools/audio.d.ts.map +1 -0
  76. package/dist/tools/audio.js.map +1 -0
  77. package/dist/tools/base-tool.d.ts.map +1 -0
  78. package/dist/tools/base-tool.js.map +1 -0
  79. package/dist/tools/behavior-tree.d.ts.map +1 -0
  80. package/dist/tools/behavior-tree.js.map +1 -0
  81. package/dist/tools/blueprint.d.ts.map +1 -0
  82. package/dist/tools/blueprint.js +4 -2
  83. package/dist/tools/blueprint.js.map +1 -0
  84. package/dist/tools/consolidated-tool-definitions.d.ts.map +1 -0
  85. package/dist/tools/consolidated-tool-definitions.js.map +1 -0
  86. package/dist/tools/consolidated-tool-handlers.d.ts.map +1 -0
  87. package/dist/tools/consolidated-tool-handlers.js.map +1 -0
  88. package/dist/tools/debug.d.ts.map +1 -0
  89. package/dist/tools/debug.js +3 -1
  90. package/dist/tools/debug.js.map +1 -0
  91. package/dist/tools/dynamic-handler-registry.d.ts.map +1 -0
  92. package/dist/tools/dynamic-handler-registry.js +3 -1
  93. package/dist/tools/dynamic-handler-registry.js.map +1 -0
  94. package/dist/tools/editor.d.ts.map +1 -0
  95. package/dist/tools/editor.js +1 -1
  96. package/dist/tools/editor.js.map +1 -0
  97. package/dist/tools/engine.d.ts.map +1 -0
  98. package/dist/tools/engine.js.map +1 -0
  99. package/dist/tools/environment.d.ts.map +1 -0
  100. package/dist/tools/environment.js +2 -2
  101. package/dist/tools/environment.js.map +1 -0
  102. package/dist/tools/foliage.d.ts.map +1 -0
  103. package/dist/tools/foliage.js.map +1 -0
  104. package/dist/tools/handlers/actor-handlers.d.ts +1 -1
  105. package/dist/tools/handlers/actor-handlers.d.ts.map +1 -0
  106. package/dist/tools/handlers/actor-handlers.js +6 -5
  107. package/dist/tools/handlers/actor-handlers.js.map +1 -0
  108. package/dist/tools/handlers/animation-handlers.d.ts.map +1 -0
  109. package/dist/tools/handlers/animation-handlers.js.map +1 -0
  110. package/dist/tools/handlers/argument-helper.d.ts.map +1 -0
  111. package/dist/tools/handlers/argument-helper.js.map +1 -0
  112. package/dist/tools/handlers/asset-handlers.d.ts.map +1 -0
  113. package/dist/tools/handlers/asset-handlers.js +5 -1
  114. package/dist/tools/handlers/asset-handlers.js.map +1 -0
  115. package/dist/tools/handlers/audio-handlers.d.ts.map +1 -0
  116. package/dist/tools/handlers/audio-handlers.js.map +1 -0
  117. package/dist/tools/handlers/blueprint-handlers.d.ts.map +1 -0
  118. package/dist/tools/handlers/blueprint-handlers.js +2 -1
  119. package/dist/tools/handlers/blueprint-handlers.js.map +1 -0
  120. package/dist/tools/handlers/common-handlers.d.ts.map +1 -0
  121. package/dist/tools/handlers/common-handlers.js.map +1 -0
  122. package/dist/tools/handlers/editor-handlers.d.ts.map +1 -0
  123. package/dist/tools/handlers/editor-handlers.js +12 -2
  124. package/dist/tools/handlers/editor-handlers.js.map +1 -0
  125. package/dist/tools/handlers/effect-handlers.d.ts.map +1 -0
  126. package/dist/tools/handlers/effect-handlers.js.map +1 -0
  127. package/dist/tools/handlers/environment-handlers.d.ts.map +1 -0
  128. package/dist/tools/handlers/environment-handlers.js.map +1 -0
  129. package/dist/tools/handlers/graph-handlers.d.ts.map +1 -0
  130. package/dist/tools/handlers/graph-handlers.js +61 -1
  131. package/dist/tools/handlers/graph-handlers.js.map +1 -0
  132. package/dist/tools/handlers/input-handlers.d.ts.map +1 -0
  133. package/dist/tools/handlers/input-handlers.js.map +1 -0
  134. package/dist/tools/handlers/inspect-handlers.d.ts.map +1 -0
  135. package/dist/tools/handlers/inspect-handlers.js.map +1 -0
  136. package/dist/tools/handlers/level-handlers.d.ts.map +1 -0
  137. package/dist/tools/handlers/level-handlers.js.map +1 -0
  138. package/dist/tools/handlers/lighting-handlers.d.ts.map +1 -0
  139. package/dist/tools/handlers/lighting-handlers.js +23 -1
  140. package/dist/tools/handlers/lighting-handlers.js.map +1 -0
  141. package/dist/tools/handlers/performance-handlers.d.ts.map +1 -0
  142. package/dist/tools/handlers/performance-handlers.js +15 -2
  143. package/dist/tools/handlers/performance-handlers.js.map +1 -0
  144. package/dist/tools/handlers/pipeline-handlers.d.ts.map +1 -0
  145. package/dist/tools/handlers/pipeline-handlers.js +61 -7
  146. package/dist/tools/handlers/pipeline-handlers.js.map +1 -0
  147. package/dist/tools/handlers/sequence-handlers.d.ts.map +1 -0
  148. package/dist/tools/handlers/sequence-handlers.js.map +1 -0
  149. package/dist/tools/handlers/system-handlers.d.ts.map +1 -0
  150. package/dist/tools/handlers/system-handlers.js +16 -1
  151. package/dist/tools/handlers/system-handlers.js.map +1 -0
  152. package/dist/tools/input.d.ts.map +1 -0
  153. package/dist/tools/input.js +3 -1
  154. package/dist/tools/input.js.map +1 -0
  155. package/dist/tools/introspection.d.ts.map +1 -0
  156. package/dist/tools/introspection.js.map +1 -0
  157. package/dist/tools/landscape.d.ts.map +1 -0
  158. package/dist/tools/landscape.js +3 -1
  159. package/dist/tools/landscape.js.map +1 -0
  160. package/dist/tools/level.d.ts.map +1 -0
  161. package/dist/tools/level.js.map +1 -0
  162. package/dist/tools/lighting.d.ts.map +1 -0
  163. package/dist/tools/lighting.js +3 -1
  164. package/dist/tools/lighting.js.map +1 -0
  165. package/dist/tools/logs.d.ts.map +1 -0
  166. package/dist/tools/logs.js.map +1 -0
  167. package/dist/tools/materials.d.ts.map +1 -0
  168. package/dist/tools/materials.js +3 -1
  169. package/dist/tools/materials.js.map +1 -0
  170. package/dist/tools/niagara.d.ts.map +1 -0
  171. package/dist/tools/niagara.js +7 -5
  172. package/dist/tools/niagara.js.map +1 -0
  173. package/dist/tools/performance.d.ts.map +1 -0
  174. package/dist/tools/performance.js.map +1 -0
  175. package/dist/tools/physics.d.ts.map +1 -0
  176. package/dist/tools/physics.js +9 -7
  177. package/dist/tools/physics.js.map +1 -0
  178. package/dist/tools/property-dictionary.d.ts.map +1 -0
  179. package/dist/tools/property-dictionary.js.map +1 -0
  180. package/dist/tools/sequence.d.ts.map +1 -0
  181. package/dist/tools/sequence.js +3 -1
  182. package/dist/tools/sequence.js.map +1 -0
  183. package/dist/tools/tool-definition-utils.d.ts.map +1 -0
  184. package/dist/tools/tool-definition-utils.js.map +1 -0
  185. package/dist/tools/ui.d.ts.map +1 -0
  186. package/dist/tools/ui.js +3 -1
  187. package/dist/tools/ui.js.map +1 -0
  188. package/dist/types/automation-responses.d.ts.map +1 -0
  189. package/dist/types/automation-responses.js.map +1 -0
  190. package/dist/types/env.d.ts.map +1 -0
  191. package/dist/types/env.js.map +1 -0
  192. package/dist/types/handler-types.d.ts.map +1 -0
  193. package/dist/types/handler-types.js.map +1 -0
  194. package/dist/types/tool-interfaces.d.ts.map +1 -0
  195. package/dist/types/tool-interfaces.js.map +1 -0
  196. package/dist/types/tool-types.d.ts.map +1 -0
  197. package/dist/types/tool-types.js.map +1 -0
  198. package/dist/unreal-bridge.d.ts +1 -0
  199. package/dist/unreal-bridge.d.ts.map +1 -0
  200. package/dist/unreal-bridge.js +8 -0
  201. package/dist/unreal-bridge.js.map +1 -0
  202. package/dist/utils/command-validator.d.ts.map +1 -0
  203. package/dist/utils/command-validator.js.map +1 -0
  204. package/dist/utils/elicitation.d.ts.map +1 -0
  205. package/dist/utils/elicitation.js.map +1 -0
  206. package/dist/utils/error-handler.d.ts.map +1 -0
  207. package/dist/utils/error-handler.js.map +1 -0
  208. package/dist/utils/ini-reader.d.ts.map +1 -0
  209. package/dist/utils/ini-reader.js.map +1 -0
  210. package/dist/utils/logger.d.ts.map +1 -0
  211. package/dist/utils/logger.js.map +1 -0
  212. package/dist/utils/normalize.d.ts.map +1 -0
  213. package/dist/utils/normalize.js.map +1 -0
  214. package/dist/utils/path-security.d.ts.map +1 -0
  215. package/dist/utils/path-security.js.map +1 -0
  216. package/dist/utils/response-factory.d.ts.map +1 -0
  217. package/dist/utils/response-factory.js +3 -1
  218. package/dist/utils/response-factory.js.map +1 -0
  219. package/dist/utils/response-validator.d.ts.map +1 -0
  220. package/dist/utils/response-validator.js.map +1 -0
  221. package/dist/utils/result-helpers.d.ts.map +1 -0
  222. package/dist/utils/result-helpers.js.map +1 -0
  223. package/dist/utils/safe-json.d.ts.map +1 -0
  224. package/dist/utils/safe-json.js.map +1 -0
  225. package/dist/utils/unreal-command-queue.d.ts.map +1 -0
  226. package/dist/utils/unreal-command-queue.js.map +1 -0
  227. package/dist/utils/validation.d.ts.map +1 -0
  228. package/dist/utils/validation.js.map +1 -0
  229. package/dist/wasm/index.d.ts.map +1 -0
  230. package/dist/wasm/index.js.map +1 -0
  231. package/package.json +12 -34
  232. package/server.json +2 -2
  233. package/.dockerignore +0 -57
  234. package/.env.example +0 -26
  235. package/.env.production +0 -61
  236. package/.eslintrc.json +0 -0
  237. package/.eslintrc.override.json +0 -8
  238. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -94
  239. package/.github/ISSUE_TEMPLATE/config.yml +0 -8
  240. package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -56
  241. package/.github/copilot-instructions.md +0 -478
  242. package/.github/dependabot.yml +0 -19
  243. package/.github/labeler.yml +0 -24
  244. package/.github/labels.yml +0 -70
  245. package/.github/pull_request_template.md +0 -42
  246. package/.github/release-drafter-config.yml +0 -51
  247. package/.github/workflows/auto-merge.yml +0 -38
  248. package/.github/workflows/ci.yml +0 -38
  249. package/.github/workflows/dependency-review.yml +0 -17
  250. package/.github/workflows/gemini-issue-triage.yml +0 -172
  251. package/.github/workflows/greetings.yml +0 -27
  252. package/.github/workflows/labeler.yml +0 -17
  253. package/.github/workflows/links.yml +0 -80
  254. package/.github/workflows/pr-size-labeler.yml +0 -137
  255. package/.github/workflows/publish-mcp.yml +0 -79
  256. package/.github/workflows/release-drafter.yml +0 -24
  257. package/.github/workflows/release.yml +0 -112
  258. package/.github/workflows/semantic-pull-request.yml +0 -35
  259. package/.github/workflows/smoke-test.yml +0 -36
  260. package/.github/workflows/stale.yml +0 -28
  261. package/CONTRIBUTING.md +0 -140
  262. package/Dockerfile +0 -37
  263. package/GEMINI.md +0 -115
  264. package/Public/Plugin_setup_guide.mp4 +0 -0
  265. package/Public/icon.png +0 -0
  266. package/claude_desktop_config_example.json +0 -15
  267. package/dist/types/responses.d.ts +0 -249
  268. package/dist/types/responses.js +0 -2
  269. package/docs/GraphQL-API.md +0 -888
  270. package/docs/Migration-Guide-v0.5.0.md +0 -684
  271. package/docs/Roadmap.md +0 -53
  272. package/docs/WebAssembly-Integration.md +0 -628
  273. package/docs/editor-plugin-extension.md +0 -370
  274. package/docs/handler-mapping.md +0 -249
  275. package/docs/native-automation-progress.md +0 -128
  276. package/docs/testing-guide.md +0 -423
  277. package/eslint.config.mjs +0 -68
  278. package/mcp-config-example.json +0 -14
  279. package/plugins/McpAutomationBridge/Config/FilterPlugin.ini +0 -8
  280. package/plugins/McpAutomationBridge/McpAutomationBridge.uplugin +0 -64
  281. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/McpAutomationBridge.Build.cs +0 -189
  282. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.cpp +0 -22
  283. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.h +0 -30
  284. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeHelpers.h +0 -1983
  285. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeModule.cpp +0 -72
  286. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSettings.cpp +0 -46
  287. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSubsystem.cpp +0 -846
  288. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AnimationHandlers.cpp +0 -2393
  289. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetQueryHandlers.cpp +0 -300
  290. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetWorkflowHandlers.cpp +0 -2807
  291. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AudioHandlers.cpp +0 -1087
  292. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BehaviorTreeHandlers.cpp +0 -488
  293. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.cpp +0 -643
  294. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.h +0 -31
  295. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintGraphHandlers.cpp +0 -1094
  296. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers.cpp +0 -5750
  297. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers_List.cpp +0 -152
  298. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ControlHandlers.cpp +0 -2614
  299. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_DebugHandlers.cpp +0 -42
  300. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EditorFunctionHandlers.cpp +0 -1237
  301. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EffectHandlers.cpp +0 -1725
  302. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EnvironmentHandlers.cpp +0 -2241
  303. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_FoliageHandlers.cpp +0 -954
  304. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InputHandlers.cpp +0 -209
  305. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InsightsHandlers.cpp +0 -41
  306. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LandscapeHandlers.cpp +0 -1164
  307. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LevelHandlers.cpp +0 -762
  308. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LightingHandlers.cpp +0 -663
  309. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LogHandlers.cpp +0 -136
  310. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_MaterialGraphHandlers.cpp +0 -494
  311. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraGraphHandlers.cpp +0 -278
  312. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraHandlers.cpp +0 -625
  313. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PerformanceHandlers.cpp +0 -401
  314. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PipelineHandlers.cpp +0 -67
  315. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ProcessRequest.cpp +0 -472
  316. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PropertyHandlers.cpp +0 -2634
  317. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_RenderHandlers.cpp +0 -189
  318. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.cpp +0 -917
  319. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.h +0 -39
  320. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequenceHandlers.cpp +0 -2706
  321. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequencerHandlers.cpp +0 -519
  322. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_TestHandlers.cpp +0 -38
  323. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_UiHandlers.cpp +0 -668
  324. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_WorldPartitionHandlers.cpp +0 -346
  325. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.cpp +0 -1330
  326. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.h +0 -149
  327. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpConnectionManager.cpp +0 -782
  328. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSettings.h +0 -115
  329. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSubsystem.h +0 -796
  330. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpConnectionManager.h +0 -117
  331. package/scripts/check-unreal-connection.mjs +0 -19
  332. package/scripts/clean-tmp.js +0 -23
  333. package/scripts/patch-wasm.js +0 -26
  334. package/scripts/run-all-tests.mjs +0 -136
  335. package/scripts/smoke-test.ts +0 -94
  336. package/scripts/sync-mcp-plugin.js +0 -143
  337. package/scripts/test-no-plugin-alternates.mjs +0 -113
  338. package/scripts/validate-server.js +0 -46
  339. package/scripts/verify-automation-bridge.js +0 -200
  340. package/src/automation/bridge.ts +0 -560
  341. package/src/automation/connection-manager.ts +0 -148
  342. package/src/automation/handshake.ts +0 -99
  343. package/src/automation/index.ts +0 -2
  344. package/src/automation/message-handler.ts +0 -192
  345. package/src/automation/request-tracker.ts +0 -155
  346. package/src/automation/types.ts +0 -107
  347. package/src/cli.ts +0 -34
  348. package/src/config/class-aliases.ts +0 -65
  349. package/src/config.ts +0 -73
  350. package/src/constants.ts +0 -24
  351. package/src/graphql/loaders.ts +0 -244
  352. package/src/graphql/resolvers.ts +0 -1008
  353. package/src/graphql/schema.ts +0 -452
  354. package/src/graphql/server.ts +0 -156
  355. package/src/graphql/types.ts +0 -10
  356. package/src/handlers/resource-handlers.ts +0 -186
  357. package/src/index.ts +0 -243
  358. package/src/resources/actors.ts +0 -127
  359. package/src/resources/assets.ts +0 -286
  360. package/src/resources/levels.ts +0 -68
  361. package/src/server/resource-registry.ts +0 -47
  362. package/src/server/tool-registry.ts +0 -354
  363. package/src/server-setup.ts +0 -114
  364. package/src/services/health-monitor.ts +0 -132
  365. package/src/services/metrics-server.ts +0 -176
  366. package/src/tools/actors.ts +0 -564
  367. package/src/tools/animation.ts +0 -941
  368. package/src/tools/assets.ts +0 -394
  369. package/src/tools/audio.ts +0 -499
  370. package/src/tools/base-tool.ts +0 -52
  371. package/src/tools/behavior-tree.ts +0 -45
  372. package/src/tools/blueprint.ts +0 -940
  373. package/src/tools/consolidated-tool-definitions.ts +0 -1256
  374. package/src/tools/consolidated-tool-handlers.ts +0 -302
  375. package/src/tools/debug.ts +0 -622
  376. package/src/tools/dynamic-handler-registry.ts +0 -33
  377. package/src/tools/editor.ts +0 -435
  378. package/src/tools/engine.ts +0 -43
  379. package/src/tools/environment.ts +0 -281
  380. package/src/tools/foliage.ts +0 -596
  381. package/src/tools/handlers/actor-handlers.ts +0 -244
  382. package/src/tools/handlers/animation-handlers.ts +0 -237
  383. package/src/tools/handlers/argument-helper.ts +0 -142
  384. package/src/tools/handlers/asset-handlers.ts +0 -550
  385. package/src/tools/handlers/audio-handlers.ts +0 -194
  386. package/src/tools/handlers/blueprint-handlers.ts +0 -380
  387. package/src/tools/handlers/common-handlers.ts +0 -108
  388. package/src/tools/handlers/editor-handlers.ts +0 -124
  389. package/src/tools/handlers/effect-handlers.ts +0 -224
  390. package/src/tools/handlers/environment-handlers.ts +0 -183
  391. package/src/tools/handlers/graph-handlers.ts +0 -117
  392. package/src/tools/handlers/input-handlers.ts +0 -28
  393. package/src/tools/handlers/inspect-handlers.ts +0 -450
  394. package/src/tools/handlers/level-handlers.ts +0 -253
  395. package/src/tools/handlers/lighting-handlers.ts +0 -151
  396. package/src/tools/handlers/performance-handlers.ts +0 -132
  397. package/src/tools/handlers/pipeline-handlers.ts +0 -128
  398. package/src/tools/handlers/sequence-handlers.ts +0 -438
  399. package/src/tools/handlers/system-handlers.ts +0 -564
  400. package/src/tools/input.ts +0 -160
  401. package/src/tools/introspection.ts +0 -689
  402. package/src/tools/landscape.ts +0 -649
  403. package/src/tools/level.ts +0 -989
  404. package/src/tools/lighting.ts +0 -1052
  405. package/src/tools/logs.ts +0 -219
  406. package/src/tools/materials.ts +0 -295
  407. package/src/tools/niagara.ts +0 -485
  408. package/src/tools/performance.ts +0 -661
  409. package/src/tools/physics.ts +0 -679
  410. package/src/tools/property-dictionary.ts +0 -98
  411. package/src/tools/sequence.ts +0 -385
  412. package/src/tools/tool-definition-utils.ts +0 -35
  413. package/src/tools/ui.ts +0 -452
  414. package/src/types/automation-responses.ts +0 -119
  415. package/src/types/env.ts +0 -17
  416. package/src/types/handler-types.ts +0 -442
  417. package/src/types/responses.ts +0 -355
  418. package/src/types/tool-interfaces.ts +0 -250
  419. package/src/types/tool-types.ts +0 -575
  420. package/src/unreal-bridge.ts +0 -693
  421. package/src/utils/command-validator.ts +0 -139
  422. package/src/utils/elicitation.ts +0 -132
  423. package/src/utils/error-handler.ts +0 -287
  424. package/src/utils/ini-reader.ts +0 -86
  425. package/src/utils/logger.ts +0 -35
  426. package/src/utils/normalize.test.ts +0 -162
  427. package/src/utils/normalize.ts +0 -146
  428. package/src/utils/path-security.ts +0 -43
  429. package/src/utils/response-factory.ts +0 -44
  430. package/src/utils/response-validator.ts +0 -395
  431. package/src/utils/result-helpers.ts +0 -195
  432. package/src/utils/safe-json.test.ts +0 -90
  433. package/src/utils/safe-json.ts +0 -70
  434. package/src/utils/unreal-command-queue.ts +0 -166
  435. package/src/utils/validation.test.ts +0 -184
  436. package/src/utils/validation.ts +0 -312
  437. package/src/wasm/index.ts +0 -838
  438. package/test-server.mjs +0 -100
  439. package/tests/run-unreal-tool-tests.mjs +0 -948
  440. package/tests/test-animation.mjs +0 -369
  441. package/tests/test-asset-advanced.mjs +0 -82
  442. package/tests/test-asset-errors.mjs +0 -35
  443. package/tests/test-asset-graph.mjs +0 -311
  444. package/tests/test-audio.mjs +0 -417
  445. package/tests/test-automation-timeouts.mjs +0 -98
  446. package/tests/test-behavior-tree.mjs +0 -444
  447. package/tests/test-blueprint-graph.mjs +0 -410
  448. package/tests/test-blueprint.mjs +0 -577
  449. package/tests/test-client-mode.mjs +0 -86
  450. package/tests/test-console-command.mjs +0 -56
  451. package/tests/test-control-actor.mjs +0 -425
  452. package/tests/test-control-editor.mjs +0 -112
  453. package/tests/test-graphql.mjs +0 -372
  454. package/tests/test-input.mjs +0 -349
  455. package/tests/test-inspect.mjs +0 -302
  456. package/tests/test-landscape.mjs +0 -316
  457. package/tests/test-lighting.mjs +0 -428
  458. package/tests/test-manage-asset.mjs +0 -438
  459. package/tests/test-manage-level.mjs +0 -89
  460. package/tests/test-materials.mjs +0 -356
  461. package/tests/test-niagara.mjs +0 -185
  462. package/tests/test-no-inline-python.mjs +0 -122
  463. package/tests/test-performance.mjs +0 -539
  464. package/tests/test-plugin-handshake.mjs +0 -82
  465. package/tests/test-runner.mjs +0 -933
  466. package/tests/test-sequence.mjs +0 -104
  467. package/tests/test-system.mjs +0 -96
  468. package/tests/test-wasm.mjs +0 -283
  469. package/tests/test-world-partition.mjs +0 -215
  470. package/tsconfig.json +0 -56
  471. package/vitest.config.ts +0 -35
  472. package/wasm/Cargo.lock +0 -363
  473. package/wasm/Cargo.toml +0 -42
  474. package/wasm/LICENSE +0 -21
  475. package/wasm/README.md +0 -253
  476. package/wasm/src/dependency_resolver.rs +0 -377
  477. package/wasm/src/lib.rs +0 -153
  478. package/wasm/src/property_parser.rs +0 -271
  479. package/wasm/src/transform_math.rs +0 -396
  480. package/wasm/tests/integration.rs +0 -109
@@ -1,989 +0,0 @@
1
- import { BaseTool } from './base-tool.js';
2
- import { ILevelTools, StandardActionResponse } from '../types/tool-interfaces.js';
3
- import { LevelResponse } from '../types/automation-responses.js';
4
- import { wasmIntegration as _wasmIntegration } from '../wasm/index.js';
5
- import { sanitizePath } from '../utils/path-security.js';
6
- import {
7
- DEFAULT_OPERATION_TIMEOUT_MS,
8
- DEFAULT_ASSET_OP_TIMEOUT_MS,
9
- LONG_RUNNING_OP_TIMEOUT_MS
10
- } from '../constants.js';
11
-
12
- type LevelExportRecord = { target: string; timestamp: number; note?: string };
13
- type ManagedLevelRecord = {
14
- path: string;
15
- name: string;
16
- partitioned: boolean;
17
- streaming: boolean;
18
- loaded: boolean;
19
- visible: boolean;
20
- createdAt: number;
21
- lastSavedAt?: number;
22
- metadata?: Record<string, unknown>;
23
- exports: LevelExportRecord[];
24
- lights: Array<{ name: string; type: string; createdAt: number; details?: Record<string, unknown> }>;
25
- };
26
-
27
- export class LevelTools extends BaseTool implements ILevelTools {
28
- private managedLevels = new Map<string, ManagedLevelRecord>();
29
- private listCache?: { result: { success: true; message: string; count: number; levels: any[] }; timestamp: number };
30
- private readonly LIST_CACHE_TTL_MS = 750;
31
- private currentLevelPath?: string;
32
-
33
- private invalidateListCache() {
34
- this.listCache = undefined;
35
- }
36
-
37
- private normalizeLevelPath(rawPath: string | undefined): { path: string; name: string } {
38
- if (!rawPath) {
39
- return { path: '/Game/Maps/Untitled', name: 'Untitled' };
40
- }
41
-
42
- let formatted = rawPath.replace(/\\/g, '/').trim();
43
- if (!formatted.startsWith('/')) {
44
- formatted = formatted.startsWith('Game/') ? `/${formatted}` : `/Game/${formatted.replace(/^\/?Game\//i, '')}`;
45
- }
46
- if (!formatted.startsWith('/Game/')) {
47
- formatted = `/Game/${formatted.replace(/^\/+/, '')}`;
48
- }
49
-
50
- // Security validation
51
- try {
52
- formatted = sanitizePath(formatted);
53
- } catch (e: unknown) {
54
- // If sanitizePath fails, we should probably propagate that error,
55
- // but normalizeLevelPath signature expects to return an object.
56
- // For now, let's log and rethrow or fallback?
57
- // Throwing is safer as it prevents operation on invalid path.
58
- throw new Error(`Security validation failed for level path: ${e instanceof Error ? e.message : String(e)}`);
59
- }
60
-
61
- formatted = formatted.replace(/\.umap$/i, '');
62
- if (formatted.endsWith('/')) {
63
- formatted = formatted.slice(0, -1);
64
- }
65
- const segments = formatted.split('/').filter(Boolean);
66
- const lastSegment = segments[segments.length - 1] ?? 'Untitled';
67
- const name = lastSegment.includes('.') ? lastSegment.split('.').pop() ?? lastSegment : lastSegment;
68
- return { path: formatted, name: name || 'Untitled' };
69
- }
70
-
71
- private ensureRecord(path: string, seed?: Partial<ManagedLevelRecord>): ManagedLevelRecord {
72
- const normalized = this.normalizeLevelPath(path);
73
- let record = this.managedLevels.get(normalized.path);
74
- if (!record) {
75
- record = {
76
- path: normalized.path,
77
- name: seed?.name ?? normalized.name,
78
- partitioned: seed?.partitioned ?? false,
79
- streaming: seed?.streaming ?? false,
80
- loaded: seed?.loaded ?? false,
81
- visible: seed?.visible ?? false,
82
- createdAt: seed?.createdAt ?? Date.now(),
83
- lastSavedAt: seed?.lastSavedAt,
84
- metadata: seed?.metadata ? { ...seed.metadata } : undefined,
85
- exports: seed?.exports ? [...seed.exports] : [],
86
- lights: seed?.lights ? [...seed.lights] : []
87
- };
88
- this.managedLevels.set(normalized.path, record);
89
- this.invalidateListCache();
90
- }
91
- return record;
92
- }
93
-
94
- private mutateRecord(path: string | undefined, updates: Partial<ManagedLevelRecord>): ManagedLevelRecord | undefined {
95
- if (!path || !path.trim()) {
96
- return undefined;
97
- }
98
-
99
- const record = this.ensureRecord(path, updates);
100
- let changed = false;
101
-
102
- if (updates.name !== undefined && updates.name !== record.name) {
103
- record.name = updates.name;
104
- changed = true;
105
- }
106
- if (updates.partitioned !== undefined && updates.partitioned !== record.partitioned) {
107
- record.partitioned = updates.partitioned;
108
- changed = true;
109
- }
110
- if (updates.streaming !== undefined && updates.streaming !== record.streaming) {
111
- record.streaming = updates.streaming;
112
- changed = true;
113
- }
114
- if (updates.loaded !== undefined && updates.loaded !== record.loaded) {
115
- record.loaded = updates.loaded;
116
- changed = true;
117
- }
118
- if (updates.visible !== undefined && updates.visible !== record.visible) {
119
- record.visible = updates.visible;
120
- changed = true;
121
- }
122
- if (updates.createdAt !== undefined && updates.createdAt !== record.createdAt) {
123
- record.createdAt = updates.createdAt;
124
- changed = true;
125
- }
126
- if (updates.lastSavedAt !== undefined && updates.lastSavedAt !== record.lastSavedAt) {
127
- record.lastSavedAt = updates.lastSavedAt;
128
- changed = true;
129
- }
130
- if (updates.metadata) {
131
- record.metadata = { ...(record.metadata ?? {}), ...updates.metadata };
132
- changed = true;
133
- }
134
- if (updates.exports && updates.exports.length > 0) {
135
- record.exports = [...record.exports, ...updates.exports];
136
- changed = true;
137
- }
138
- if (updates.lights && updates.lights.length > 0) {
139
- record.lights = [...record.lights, ...updates.lights];
140
- changed = true;
141
- }
142
-
143
- if (changed) {
144
- this.invalidateListCache();
145
- }
146
-
147
- return record;
148
- }
149
-
150
- private getRecord(path: string | undefined): ManagedLevelRecord | undefined {
151
- if (!path || !path.trim()) {
152
- return undefined;
153
- }
154
- const normalized = this.normalizeLevelPath(path);
155
- return this.managedLevels.get(normalized.path);
156
- }
157
-
158
- private resolveLevelPath(explicit?: string): string | undefined {
159
- if (explicit && explicit.trim()) {
160
- return this.normalizeLevelPath(explicit).path;
161
- }
162
- return this.currentLevelPath;
163
- }
164
-
165
- private removeRecord(path: string) {
166
- const normalized = this.normalizeLevelPath(path);
167
- if (this.managedLevels.delete(normalized.path)) {
168
- if (this.currentLevelPath === normalized.path) {
169
- this.currentLevelPath = undefined;
170
- }
171
- this.invalidateListCache();
172
- }
173
- }
174
-
175
- private listManagedLevels(): { success: true; message: string; count: number; levels: Array<Record<string, unknown>> } {
176
- const now = Date.now();
177
- if (this.listCache && now - this.listCache.timestamp < this.LIST_CACHE_TTL_MS) {
178
- return this.listCache.result;
179
- }
180
-
181
- const levels = Array.from(this.managedLevels.values()).map((record) => ({
182
- path: record.path,
183
- name: record.name,
184
- partitioned: record.partitioned,
185
- streaming: record.streaming,
186
- loaded: record.loaded,
187
- visible: record.visible,
188
- createdAt: record.createdAt,
189
- lastSavedAt: record.lastSavedAt,
190
- exports: record.exports,
191
- lightCount: record.lights.length
192
- }));
193
-
194
- const result = { success: true as const, message: 'Managed levels listed', count: levels.length, levels };
195
- this.listCache = { result, timestamp: now };
196
- return result;
197
- }
198
-
199
- private summarizeLevel(path: string): Record<string, unknown> {
200
- const record = this.getRecord(path);
201
- if (!record) {
202
- return { success: false, error: `Level not tracked: ${path}` };
203
- }
204
-
205
- return {
206
- success: true,
207
- message: 'Level summary ready',
208
- path: record.path,
209
- name: record.name,
210
- partitioned: record.partitioned,
211
- streaming: record.streaming,
212
- loaded: record.loaded,
213
- visible: record.visible,
214
- createdAt: record.createdAt,
215
- lastSavedAt: record.lastSavedAt,
216
- exports: record.exports,
217
- lights: record.lights,
218
- metadata: record.metadata
219
- };
220
- }
221
-
222
- private setCurrentLevel(path: string) {
223
- const normalized = this.normalizeLevelPath(path);
224
- this.currentLevelPath = normalized.path;
225
- this.ensureRecord(normalized.path, { loaded: true, visible: true });
226
- }
227
-
228
- async listLevels(): Promise<StandardActionResponse> {
229
- // Try to get actual levels from UE via automation bridge
230
- try {
231
- const response = await this.sendAutomationRequest<LevelResponse>('list_levels', {}, {
232
- timeoutMs: 10000
233
- });
234
-
235
- if (response && response.success !== false) {
236
- // Also include managed levels for backwards compatibility and immediate visibility
237
- const managed = this.listManagedLevels();
238
-
239
- // Merge managed levels into the main list if not already present
240
- const ueLevels = (response.allMaps || []) as any[];
241
- const managedOnly = managed.levels.filter(m => !ueLevels.some(u => u.path === m.path));
242
- const finalLevels = [...ueLevels, ...managedOnly];
243
-
244
- const result: Record<string, unknown> = {
245
- ...response,
246
- success: true,
247
- message: 'Levels listed from Unreal Engine',
248
- levels: finalLevels,
249
- currentMap: response.currentMap,
250
- currentMapPath: response.currentMapPath,
251
- currentWorldLevels: response.currentWorldLevels || [],
252
- data: {
253
- levels: finalLevels,
254
- count: finalLevels.length
255
- },
256
- managedLevels: managed.levels,
257
- managedLevelCount: managed.count
258
- };
259
-
260
- return result as StandardActionResponse;
261
- }
262
- } catch {
263
- // Fall back to managed levels if automation bridge fails
264
- }
265
-
266
- // Fallback to locally managed levels
267
- return this.listManagedLevels();
268
- }
269
-
270
- async getLevelSummary(levelPath?: string): Promise<StandardActionResponse> {
271
- const resolved = this.resolveLevelPath(levelPath);
272
- if (!resolved) {
273
- return { success: false, error: 'No level specified' };
274
- }
275
- return this.summarizeLevel(resolved) as StandardActionResponse;
276
- }
277
-
278
- registerLight(levelPath: string | undefined, info: { name: string; type: string; details?: Record<string, unknown> }) {
279
- const resolved = this.resolveLevelPath(levelPath);
280
- if (!resolved) {
281
- return;
282
- }
283
- this.mutateRecord(resolved, {
284
- lights: [
285
- {
286
- name: info.name,
287
- type: info.type,
288
- createdAt: Date.now(),
289
- details: info.details
290
- }
291
- ]
292
- });
293
- }
294
-
295
- async exportLevel(params: { levelPath?: string; exportPath: string; note?: string; timeoutMs?: number }): Promise<StandardActionResponse> {
296
- const resolved = this.resolveLevelPath(params.levelPath);
297
- if (!resolved) {
298
- return { success: false, error: 'No level specified for export' };
299
- }
300
-
301
- try {
302
- const res = await this.sendAutomationRequest<LevelResponse>('manage_level', {
303
- action: 'export_level',
304
- levelPath: resolved,
305
- exportPath: params.exportPath
306
- }, { timeoutMs: params.timeoutMs ?? LONG_RUNNING_OP_TIMEOUT_MS });
307
-
308
- if (res?.success === false) {
309
- return {
310
- success: false,
311
- error: res.error || res.message || 'Export failed',
312
- levelPath: resolved,
313
- exportPath: params.exportPath,
314
- details: res
315
- } as StandardActionResponse;
316
- }
317
-
318
- return {
319
- success: true,
320
- message: `Level exported to ${params.exportPath}`,
321
- levelPath: resolved,
322
- exportPath: params.exportPath,
323
- details: res
324
- } as StandardActionResponse;
325
- } catch (e: unknown) {
326
- return { success: false, error: `Export failed: ${e instanceof Error ? e.message : String(e)}` };
327
- }
328
- }
329
-
330
- async importLevel(params: { packagePath: string; destinationPath?: string; streaming?: boolean; timeoutMs?: number }): Promise<StandardActionResponse> {
331
- const destination = params.destinationPath
332
- ? this.normalizeLevelPath(params.destinationPath)
333
- : this.normalizeLevelPath(`/Game/Maps/Imported_${Math.floor(Date.now() / 1000)}`);
334
-
335
- try {
336
- const res = await this.sendAutomationRequest<LevelResponse>('manage_level', {
337
- action: 'import_level',
338
- packagePath: params.packagePath,
339
- destinationPath: destination.path
340
- }, { timeoutMs: params.timeoutMs ?? LONG_RUNNING_OP_TIMEOUT_MS });
341
-
342
- if ((res as any)?.success === false) {
343
- return {
344
- success: false,
345
- error: (res as any).error || (res as any).message || 'Import failed',
346
- levelPath: destination.path,
347
- details: res
348
- } as StandardActionResponse;
349
- }
350
-
351
- return {
352
- success: true,
353
- message: `Level imported to ${destination.path}`,
354
- levelPath: destination.path,
355
- partitioned: true,
356
- streaming: Boolean(params.streaming),
357
- details: res
358
- } as StandardActionResponse;
359
- } catch (e: unknown) {
360
- return { success: false, error: `Import failed: ${e instanceof Error ? e.message : String(e)}` };
361
- }
362
- }
363
-
364
- async saveLevelAs(params: { sourcePath?: string; targetPath: string }): Promise<StandardActionResponse> {
365
- const source = this.resolveLevelPath(params.sourcePath);
366
- const target = this.normalizeLevelPath(params.targetPath);
367
-
368
- // Delegate to automation bridge
369
- try {
370
- const response = await this.sendAutomationRequest<LevelResponse>('manage_level', {
371
- action: 'save_level_as',
372
- savePath: target.path
373
- }, {
374
- timeoutMs: DEFAULT_ASSET_OP_TIMEOUT_MS
375
- });
376
-
377
- if (response.success === false) {
378
- return { success: false, error: response.error || response.message || 'Failed to save level as' };
379
- }
380
-
381
- // If successful, update local state
382
- if (!source) {
383
- // If no source known, just ensure target record
384
- this.ensureRecord(target.path, {
385
- name: target.name,
386
- loaded: true,
387
- visible: true,
388
- createdAt: Date.now(),
389
- lastSavedAt: Date.now()
390
- });
391
- } else {
392
- const sourceRecord = this.getRecord(source);
393
- const now = Date.now();
394
- this.ensureRecord(target.path, {
395
- name: target.name,
396
- partitioned: sourceRecord?.partitioned ?? true,
397
- streaming: sourceRecord?.streaming ?? false,
398
- loaded: true,
399
- visible: true,
400
- metadata: { ...(sourceRecord?.metadata ?? {}), savedFrom: source },
401
- exports: sourceRecord?.exports ?? [],
402
- lights: sourceRecord?.lights ?? [],
403
- createdAt: sourceRecord?.createdAt ?? now,
404
- lastSavedAt: now
405
- });
406
- }
407
-
408
- this.setCurrentLevel(target.path);
409
-
410
- return {
411
- success: true,
412
- message: response.message || `Level saved as ${target.path}`,
413
- levelPath: target.path
414
- } as StandardActionResponse;
415
- } catch (error) {
416
- return { success: false, error: `Failed to save level as: ${error instanceof Error ? error.message : String(error)}` };
417
- }
418
- }
419
-
420
- async deleteLevels(params: { levelPaths: string[] }): Promise<StandardActionResponse> {
421
- const removed: string[] = [];
422
- for (const path of params.levelPaths) {
423
- const normalized = this.normalizeLevelPath(path).path;
424
- if (this.managedLevels.has(normalized)) {
425
- this.removeRecord(normalized);
426
- removed.push(normalized);
427
- }
428
- }
429
-
430
- return {
431
- success: true,
432
- message: removed.length ? `Deleted ${removed.length} managed level(s)` : 'No managed levels removed',
433
- removed
434
- } as StandardActionResponse;
435
- }
436
-
437
- async loadLevel(params: {
438
- levelPath: string;
439
- streaming?: boolean;
440
- position?: [number, number, number];
441
- }): Promise<StandardActionResponse> {
442
- const normalizedPath = this.normalizeLevelPath(params.levelPath).path;
443
-
444
- if (params.streaming) {
445
- try {
446
- const simpleName = (params.levelPath || '').split('/').filter(Boolean).pop() || params.levelPath;
447
- await this.bridge.executeConsoleCommand(`StreamLevel ${simpleName} Load Show`);
448
- this.mutateRecord(normalizedPath, {
449
- streaming: true,
450
- loaded: true,
451
- visible: true
452
- });
453
- return {
454
- success: true,
455
- message: `Streaming level loaded: ${params.levelPath}`,
456
- levelPath: normalizedPath,
457
- streaming: true
458
- } as StandardActionResponse;
459
- } catch (err) {
460
- return {
461
- success: false,
462
- error: `Failed to load streaming level: ${err}`,
463
- levelPath: normalizedPath
464
- };
465
- }
466
- } else {
467
- // Try loading via automation bridge first (more robust)
468
- try {
469
- const response = await this.sendAutomationRequest<LevelResponse>('manage_level', {
470
- action: 'load',
471
- levelPath: params.levelPath
472
- }, { timeoutMs: DEFAULT_OPERATION_TIMEOUT_MS });
473
-
474
- if (response.success) {
475
- this.setCurrentLevel(normalizedPath);
476
- this.mutateRecord(normalizedPath, {
477
- streaming: false,
478
- loaded: true,
479
- visible: true
480
- });
481
- return {
482
- ...response,
483
- success: true,
484
- message: `Level loaded: ${params.levelPath}`,
485
- level: normalizedPath,
486
- streaming: false
487
- } as StandardActionResponse;
488
- }
489
- } catch (_e) {
490
- // Fallback to console logic
491
- }
492
-
493
- try {
494
- // Best-effort existence check using the Automation Bridge when available.
495
- try {
496
- const automation = this.getAutomationBridge();
497
- if (automation && typeof automation.sendAutomationRequest === 'function' && automation.isConnected()) {
498
- const targetPath = (params.levelPath ?? '').toString();
499
- const existsResp: any = await automation.sendAutomationRequest('execute_editor_function', {
500
- functionName: 'ASSET_EXISTS_SIMPLE',
501
- path: targetPath
502
- }, {
503
- timeoutMs: 5000
504
- });
505
- const result = existsResp?.result ?? existsResp ?? {};
506
- const exists = Boolean(result.exists);
507
-
508
- if (!exists) {
509
- const message = typeof result.message === 'string' ? result.message : 'Level not found';
510
- return {
511
- success: false,
512
- error: 'not_found',
513
- message,
514
- level: normalizedPath
515
- } as StandardActionResponse;
516
- }
517
- }
518
- } catch {
519
- // If the existence check fails for any reason, fall back to the console command path below.
520
- }
521
-
522
- await this.bridge.executeConsoleCommand(`Open ${params.levelPath}`);
523
- this.setCurrentLevel(normalizedPath);
524
- this.mutateRecord(normalizedPath, {
525
- streaming: false,
526
- loaded: true,
527
- visible: true
528
- });
529
- return {
530
- success: true,
531
- message: `Level loaded: ${params.levelPath}`,
532
- level: normalizedPath,
533
- streaming: false
534
- } as StandardActionResponse;
535
- } catch (err) {
536
- return {
537
- success: false,
538
- error: `Failed to load level: ${err}`,
539
- level: normalizedPath
540
- };
541
- }
542
- }
543
- }
544
-
545
- async saveLevel(params: {
546
- levelName?: string;
547
- savePath?: string;
548
- }): Promise<StandardActionResponse> {
549
- try {
550
- if (params.savePath && !params.savePath.startsWith('/Game/')) {
551
- throw new Error(`Invalid save path: ${params.savePath}`);
552
- }
553
-
554
- const action = params.savePath ? 'save_level_as' : 'save';
555
- const payload: Record<string, unknown> = { action };
556
- if (params.savePath) {
557
- payload.savePath = params.savePath;
558
- }
559
-
560
- const response = await this.sendAutomationRequest<LevelResponse>('manage_level', payload, {
561
- timeoutMs: DEFAULT_ASSET_OP_TIMEOUT_MS
562
- });
563
-
564
- if (response.success === false) {
565
- return { success: false, error: response.error || response.message || 'Failed to save level' };
566
- }
567
-
568
- const result: Record<string, unknown> = {
569
- ...response,
570
- success: true,
571
- message: response.message || 'Level saved'
572
- };
573
-
574
- if (response.skipped) {
575
- result.skipped = response.skipped;
576
- }
577
- if (response.reason) {
578
- result.reason = response.reason;
579
- }
580
- if (response.warnings) {
581
- result.warnings = response.warnings;
582
- }
583
- if (response.details) {
584
- result.details = response.details;
585
- }
586
-
587
- return result as StandardActionResponse;
588
- } catch (error) {
589
- return { success: false, error: `Failed to save level: ${error instanceof Error ? error.message : String(error)}` };
590
- }
591
- }
592
-
593
- async createLevel(params: {
594
- levelName: string;
595
- template?: 'Empty' | 'Default' | 'VR' | 'TimeOfDay';
596
- savePath?: string;
597
- }): Promise<StandardActionResponse> {
598
- const basePath = params.savePath || '/Game/Maps';
599
- const isPartitioned = true; // default to World Partition for UE5
600
- const fullPath = `${basePath}/${params.levelName}`;
601
-
602
- try {
603
- const response = await this.sendAutomationRequest<LevelResponse>('create_new_level', {
604
- levelPath: fullPath,
605
- useWorldPartition: isPartitioned
606
- }, {
607
- timeoutMs: DEFAULT_ASSET_OP_TIMEOUT_MS
608
- });
609
-
610
- if (response.success === false) {
611
- return {
612
- success: false,
613
- error: response.error || response.message || 'Failed to create level',
614
- path: fullPath,
615
- partitioned: isPartitioned
616
- } as StandardActionResponse;
617
- }
618
-
619
- const result: Record<string, unknown> = {
620
- ...response,
621
- success: true,
622
- message: response.message || 'Level created',
623
- path: response.levelPath || fullPath,
624
- packagePath: response.packagePath ?? fullPath,
625
- objectPath: response.objectPath,
626
- partitioned: isPartitioned
627
- };
628
-
629
- if (response.warnings) {
630
- result.warnings = response.warnings;
631
- }
632
- if (response.details) {
633
- result.details = response.details;
634
- }
635
-
636
- this.ensureRecord(fullPath, {
637
- name: params.levelName,
638
- partitioned: isPartitioned,
639
- loaded: true,
640
- visible: true,
641
- createdAt: Date.now()
642
- });
643
-
644
- return result as StandardActionResponse;
645
- } catch (error) {
646
- return {
647
- success: false,
648
- error: `Failed to create level: ${error instanceof Error ? error.message : String(error)}`,
649
- path: fullPath,
650
- partitioned: isPartitioned
651
- } as StandardActionResponse;
652
- }
653
- }
654
-
655
- async addSubLevel(params: {
656
- parentLevel?: string;
657
- subLevelPath: string;
658
- streamingMethod?: 'Blueprint' | 'AlwaysLoaded';
659
- }): Promise<StandardActionResponse> {
660
- const parent = params.parentLevel ? this.resolveLevelPath(params.parentLevel) : this.currentLevelPath;
661
- const sub = this.normalizeLevelPath(params.subLevelPath).path;
662
-
663
- // Use console command as primary method for adding sublevels
664
- // "WorldComposition" commands or generic "AddLevelToWorld"
665
- // Since stream_level handles existing sublevels, we just need to ADD it.
666
- // Console command: 'LevelEditor.AddLevel <Path>' works in editor context mostly, but might be tricky.
667
- // Falling back to automation request if we have const sub = this.normalizeLevelPath(params.subLevelPath).path;
668
-
669
- // Ensure path corresponds to what automation expects (Package path usually, but C++ might check file)
670
- // If C++ FPackageName::DoesPackageExist expects pure package path (e.g. /Game/Map), we are good.
671
- // But if it's recently created, it might need to receive the full path as verified in createLevel.
672
-
673
- // Attempt automation first (cleaner)
674
- try {
675
- let response = await this.sendAutomationRequest<LevelResponse>('manage_level', {
676
- action: 'add_sublevel',
677
- levelPath: sub, // Backwards compat
678
- subLevelPath: sub,
679
- parentPath: parent,
680
- streamingMethod: params.streamingMethod
681
- }, { timeoutMs: DEFAULT_OPERATION_TIMEOUT_MS });
682
-
683
- // Retry with .umap if package not found (Workaround for C++ strictness)
684
- // Also retry if ADD_FAILED, as UEditorLevelUtils might have failed due to path resolution internally
685
- if (response && (response.error === 'PACKAGE_NOT_FOUND' || response.error === 'ADD_FAILED') && !sub.endsWith('.umap')) {
686
- const subWithExt = sub + '.umap';
687
- response = await this.sendAutomationRequest<LevelResponse>('manage_level', {
688
- action: 'add_sublevel',
689
- levelPath: subWithExt,
690
- subLevelPath: subWithExt,
691
- parentPath: parent,
692
- streamingMethod: params.streamingMethod
693
- }, { timeoutMs: DEFAULT_OPERATION_TIMEOUT_MS });
694
- }
695
-
696
- if (response.success) {
697
- this.ensureRecord(sub, { loaded: true, visible: true, streaming: true });
698
- return response as StandardActionResponse;
699
- } else if (response.error === 'UNKNOWN_ACTION') {
700
- // Fallthrough to console fallback if action not implemented
701
- } else {
702
- // Return actual error if it's something else (e.g. execution failed)
703
- return response as StandardActionResponse;
704
- }
705
- } catch (_e: any) {
706
- // If connection failed, might fallback. But if we got a response, respect it.
707
- }
708
-
709
- // Console fallback
710
- // Try using LevelEditor.AddLevel command which is available in Editor context
711
- const consoleResponse = await this.sendAutomationRequest<LevelResponse>('console_command', {
712
- command: `LevelEditor.AddLevel ${sub}`
713
- });
714
-
715
- if (consoleResponse.success) {
716
- this.ensureRecord(sub, { loaded: true, visible: true, streaming: true });
717
- return {
718
- success: true,
719
- message: `Sublevel added via console: ${sub}`,
720
- data: { method: 'console' }
721
- } as StandardActionResponse;
722
- }
723
-
724
- return {
725
- success: false,
726
- error: 'Fallbacks failed',
727
- // Return the last relevant error + console error
728
- message: 'Failed to add sublevel via automation or console.',
729
- details: { consoleError: consoleResponse }
730
- } as StandardActionResponse;
731
- }
732
-
733
- async streamLevel(params: {
734
- levelPath?: string;
735
- levelName?: string;
736
- shouldBeLoaded: boolean;
737
- shouldBeVisible?: boolean;
738
- position?: [number, number, number];
739
- }): Promise<StandardActionResponse> {
740
- const rawPath = typeof params.levelPath === 'string' ? params.levelPath.trim() : '';
741
- const levelPath = rawPath.length > 0 ? rawPath : undefined;
742
- const providedName = typeof params.levelName === 'string' ? params.levelName.trim() : '';
743
- const derivedName = providedName.length > 0
744
- ? providedName
745
- : (levelPath ? levelPath.split('/').filter(Boolean).pop() ?? '' : '');
746
- const levelName = derivedName.length > 0 ? derivedName : undefined;
747
- const shouldBeVisible = params.shouldBeVisible ?? params.shouldBeLoaded;
748
-
749
- try {
750
- const response = await this.sendAutomationRequest<LevelResponse>('stream_level', {
751
- levelPath: levelPath || '',
752
- levelName: levelName || '',
753
- shouldBeLoaded: params.shouldBeLoaded,
754
- shouldBeVisible
755
- }, {
756
- timeoutMs: DEFAULT_ASSET_OP_TIMEOUT_MS
757
- });
758
-
759
- if (response.success === false) {
760
- const errorCode = typeof response.error === 'string' ? response.error : '';
761
- const isExecFailed = errorCode.toLowerCase() === 'exec_failed';
762
-
763
- if (isExecFailed) {
764
- const handledResult: Record<string, unknown> = {
765
- success: true,
766
- handled: true,
767
- message: response.message || 'Streaming level request handled (editor reported EXEC_FAILED)',
768
- level: levelName || '',
769
- levelPath,
770
- loaded: params.shouldBeLoaded,
771
- visible: shouldBeVisible
772
- };
773
-
774
- if (response.warnings) {
775
- handledResult.warnings = response.warnings;
776
- }
777
- if (response.details) {
778
- handledResult.details = response.details;
779
- }
780
-
781
- return handledResult as StandardActionResponse;
782
- }
783
-
784
- return {
785
- success: false,
786
- error: response.error || response.message || 'Streaming level update failed',
787
- level: levelName || '',
788
- levelPath: levelPath,
789
- loaded: params.shouldBeLoaded,
790
- visible: shouldBeVisible
791
- } as StandardActionResponse;
792
- }
793
-
794
- const result: Record<string, unknown> = {
795
- success: true,
796
- message: response.message || 'Streaming level updated',
797
- level: levelName || '',
798
- levelPath,
799
- loaded: params.shouldBeLoaded,
800
- visible: shouldBeVisible
801
- };
802
-
803
- if (response.warnings) {
804
- result.warnings = response.warnings;
805
- }
806
- if (response.details) {
807
- result.details = response.details;
808
- }
809
-
810
- return result as StandardActionResponse;
811
- } catch (_error) {
812
- // Fallback to console command
813
- const levelIdentifier = levelName ?? levelPath ?? '';
814
- const simpleName = levelIdentifier.split('/').filter(Boolean).pop() || levelIdentifier;
815
- const loadCmd = params.shouldBeLoaded ? 'Load' : 'Unload';
816
- const visCmd = shouldBeVisible ? 'Show' : 'Hide';
817
- const command = `StreamLevel ${simpleName} ${loadCmd} ${visCmd}`;
818
- return this.bridge.executeConsoleCommand(command);
819
- }
820
- }
821
-
822
- async setupWorldComposition(params: {
823
- enableComposition: boolean;
824
- tileSize?: number;
825
- distanceStreaming?: boolean;
826
- streamingDistance?: number;
827
- }): Promise<StandardActionResponse> {
828
- const commands: string[] = [];
829
-
830
- if (params.enableComposition) {
831
- commands.push('EnableWorldComposition');
832
- if (params.tileSize) {
833
- commands.push(`SetWorldTileSize ${params.tileSize}`);
834
- }
835
- if (params.distanceStreaming) {
836
- commands.push(`EnableDistanceStreaming ${params.streamingDistance || 5000}`);
837
- }
838
- } else {
839
- commands.push('DisableWorldComposition');
840
- }
841
-
842
- await this.bridge.executeConsoleCommands(commands);
843
-
844
- return { success: true, message: 'World composition configured' };
845
- }
846
-
847
- async editLevelBlueprint(params: {
848
- eventType: 'BeginPlay' | 'EndPlay' | 'Tick' | 'Custom';
849
- customEventName?: string;
850
- nodes?: Array<{
851
- nodeType: string;
852
- position: [number, number];
853
- connections?: string[];
854
- }>;
855
- }): Promise<StandardActionResponse> {
856
- const command = `OpenLevelBlueprint ${params.eventType}`;
857
- return this.bridge.executeConsoleCommand(command);
858
- }
859
-
860
- async createSubLevel(params: {
861
- name: string;
862
- type: 'Persistent' | 'Streaming' | 'Lighting' | 'Gameplay';
863
- parent?: string;
864
- }): Promise<StandardActionResponse> {
865
- const command = `CreateSubLevel ${params.name} ${params.type} ${params.parent || 'None'}`;
866
- return this.bridge.executeConsoleCommand(command);
867
- }
868
-
869
- async setWorldSettings(params: {
870
- gravity?: number;
871
- worldScale?: number;
872
- gameMode?: string;
873
- defaultPawn?: string;
874
- killZ?: number;
875
- }): Promise<StandardActionResponse> {
876
- const commands: string[] = [];
877
-
878
- if (params.gravity !== undefined) {
879
- commands.push(`SetWorldGravity ${params.gravity}`);
880
- }
881
- if (params.worldScale !== undefined) {
882
- commands.push(`SetWorldToMeters ${params.worldScale}`);
883
- }
884
- if (params.gameMode) {
885
- commands.push(`SetGameMode ${params.gameMode}`);
886
- }
887
- if (params.defaultPawn) {
888
- commands.push(`SetDefaultPawn ${params.defaultPawn}`);
889
- }
890
- if (params.killZ !== undefined) {
891
- commands.push(`SetKillZ ${params.killZ}`);
892
- }
893
-
894
- await this.bridge.executeConsoleCommands(commands);
895
-
896
- return { success: true, message: 'World settings updated' };
897
- }
898
-
899
- async setLevelBounds(params: {
900
- min: [number, number, number];
901
- max: [number, number, number];
902
- }): Promise<StandardActionResponse> {
903
- const command = `SetLevelBounds ${params.min.join(',')} ${params.max.join(',')}`;
904
- return this.bridge.executeConsoleCommand(command);
905
- }
906
-
907
- async buildNavMesh(params: {
908
- rebuildAll?: boolean;
909
- selectedOnly?: boolean;
910
- }): Promise<StandardActionResponse> {
911
- try {
912
- const response = await this.sendAutomationRequest<LevelResponse>('build_navigation_mesh', {
913
- rebuildAll: params.rebuildAll ?? false,
914
- selectedOnly: params.selectedOnly ?? false
915
- }, {
916
- timeoutMs: 120000
917
- });
918
-
919
- if (response.success === false) {
920
- return {
921
- success: false,
922
- error: response.error || response.message || 'Failed to build navigation'
923
- };
924
- }
925
-
926
- const result: Record<string, unknown> = {
927
- success: true,
928
- message: response.message || (params.rebuildAll ? 'Navigation rebuild started' : 'Navigation update started')
929
- };
930
-
931
- if (params.rebuildAll !== undefined) {
932
- result.rebuildAll = params.rebuildAll;
933
- }
934
- if (params.selectedOnly !== undefined) {
935
- result.selectedOnly = params.selectedOnly;
936
- }
937
- if (response.selectionCount !== undefined) {
938
- result.selectionCount = response.selectionCount;
939
- }
940
- if (response.warnings) {
941
- result.warnings = response.warnings;
942
- }
943
- if (response.details) {
944
- result.details = response.details;
945
- }
946
-
947
- return result as StandardActionResponse;
948
- } catch (error) {
949
- return {
950
- success: false,
951
- error: `Navigation build not available: ${error instanceof Error ? error.message : String(error)}. Please ensure a NavMeshBoundsVolume exists in the level.`
952
- };
953
- }
954
- }
955
-
956
- async setLevelVisibility(params: {
957
- levelName: string;
958
- visible: boolean;
959
- }): Promise<StandardActionResponse> {
960
- const command = `SetLevelVisibility ${params.levelName} ${params.visible}`;
961
- return this.bridge.executeConsoleCommand(command);
962
- }
963
-
964
- async setWorldOrigin(params: {
965
- location: [number, number, number];
966
- }): Promise<StandardActionResponse> {
967
- const command = `SetWorldOriginLocation ${params.location.join(' ')}`;
968
- return this.bridge.executeConsoleCommand(command);
969
- }
970
-
971
- async createStreamingVolume(params: {
972
- levelName: string;
973
- position: [number, number, number];
974
- size: [number, number, number];
975
- streamingDistance?: number;
976
- }): Promise<StandardActionResponse> {
977
- const command = `CreateStreamingVolume ${params.levelName} ${params.position.join(' ')} ${params.size.join(' ')} ${params.streamingDistance || 0}`;
978
- return this.bridge.executeConsoleCommand(command);
979
- }
980
-
981
- async setLevelLOD(params: {
982
- levelName: string;
983
- lodLevel: number;
984
- distance: number;
985
- }): Promise<StandardActionResponse> {
986
- const command = `SetLevelLOD ${params.levelName} ${params.lodLevel} ${params.distance}`;
987
- return this.bridge.executeConsoleCommand(command);
988
- }
989
- }