unreal-engine-mcp-server 0.5.4 → 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 (468) hide show
  1. package/dist/automation/bridge.d.ts.map +1 -0
  2. package/dist/automation/bridge.js.map +1 -0
  3. package/dist/automation/connection-manager.d.ts.map +1 -0
  4. package/dist/automation/connection-manager.js.map +1 -0
  5. package/dist/automation/handshake.d.ts.map +1 -0
  6. package/dist/automation/handshake.js.map +1 -0
  7. package/dist/automation/index.d.ts.map +1 -0
  8. package/dist/automation/index.js.map +1 -0
  9. package/dist/automation/message-handler.d.ts.map +1 -0
  10. package/dist/automation/message-handler.js.map +1 -0
  11. package/dist/automation/request-tracker.d.ts.map +1 -0
  12. package/dist/automation/request-tracker.js.map +1 -0
  13. package/dist/automation/types.d.ts.map +1 -0
  14. package/dist/automation/types.js.map +1 -0
  15. package/dist/cli.d.ts.map +1 -0
  16. package/dist/cli.js +4 -3
  17. package/dist/cli.js.map +1 -0
  18. package/dist/config/class-aliases.d.ts.map +1 -0
  19. package/dist/config/class-aliases.js.map +1 -0
  20. package/dist/config.d.ts.map +1 -0
  21. package/dist/config.js.map +1 -0
  22. package/dist/constants.d.ts.map +1 -0
  23. package/dist/constants.js.map +1 -0
  24. package/dist/graphql/loaders.d.ts.map +1 -0
  25. package/dist/graphql/loaders.js.map +1 -0
  26. package/dist/graphql/resolvers.d.ts.map +1 -0
  27. package/dist/graphql/resolvers.js +29 -29
  28. package/dist/graphql/resolvers.js.map +1 -0
  29. package/dist/graphql/schema.d.ts.map +1 -0
  30. package/dist/graphql/schema.js.map +1 -0
  31. package/dist/graphql/server.d.ts.map +1 -0
  32. package/dist/graphql/server.js.map +1 -0
  33. package/dist/graphql/types.d.ts.map +1 -0
  34. package/dist/graphql/types.js.map +1 -0
  35. package/dist/handlers/resource-handlers.d.ts.map +1 -0
  36. package/dist/handlers/resource-handlers.js.map +1 -0
  37. package/dist/index.d.ts +1 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +64 -7
  40. package/dist/index.js.map +1 -0
  41. package/dist/resources/actors.d.ts.map +1 -0
  42. package/dist/resources/actors.js.map +1 -0
  43. package/dist/resources/assets.d.ts.map +1 -0
  44. package/dist/resources/assets.js +6 -4
  45. package/dist/resources/assets.js.map +1 -0
  46. package/dist/resources/levels.d.ts.map +1 -0
  47. package/dist/resources/levels.js.map +1 -0
  48. package/dist/server/resource-registry.d.ts.map +1 -0
  49. package/dist/server/resource-registry.js.map +1 -0
  50. package/dist/server/tool-registry.d.ts.map +1 -0
  51. package/dist/server/tool-registry.js.map +1 -0
  52. package/dist/server-setup.d.ts.map +1 -0
  53. package/dist/server-setup.js.map +1 -0
  54. package/dist/services/health-monitor.d.ts.map +1 -0
  55. package/dist/services/health-monitor.js.map +1 -0
  56. package/dist/services/metrics-server.d.ts.map +1 -0
  57. package/dist/services/metrics-server.js.map +1 -0
  58. package/dist/tools/actors.d.ts.map +1 -0
  59. package/dist/tools/actors.js +3 -1
  60. package/dist/tools/actors.js.map +1 -0
  61. package/dist/tools/animation.d.ts.map +1 -0
  62. package/dist/tools/animation.js +2 -2
  63. package/dist/tools/animation.js.map +1 -0
  64. package/dist/tools/assets.d.ts.map +1 -0
  65. package/dist/tools/assets.js.map +1 -0
  66. package/dist/tools/audio.d.ts.map +1 -0
  67. package/dist/tools/audio.js.map +1 -0
  68. package/dist/tools/base-tool.d.ts.map +1 -0
  69. package/dist/tools/base-tool.js.map +1 -0
  70. package/dist/tools/behavior-tree.d.ts.map +1 -0
  71. package/dist/tools/behavior-tree.js.map +1 -0
  72. package/dist/tools/blueprint.d.ts.map +1 -0
  73. package/dist/tools/blueprint.js +4 -2
  74. package/dist/tools/blueprint.js.map +1 -0
  75. package/dist/tools/consolidated-tool-definitions.d.ts.map +1 -0
  76. package/dist/tools/consolidated-tool-definitions.js.map +1 -0
  77. package/dist/tools/consolidated-tool-handlers.d.ts.map +1 -0
  78. package/dist/tools/consolidated-tool-handlers.js.map +1 -0
  79. package/dist/tools/debug.d.ts.map +1 -0
  80. package/dist/tools/debug.js +3 -1
  81. package/dist/tools/debug.js.map +1 -0
  82. package/dist/tools/dynamic-handler-registry.d.ts.map +1 -0
  83. package/dist/tools/dynamic-handler-registry.js +3 -1
  84. package/dist/tools/dynamic-handler-registry.js.map +1 -0
  85. package/dist/tools/editor.d.ts.map +1 -0
  86. package/dist/tools/editor.js +1 -1
  87. package/dist/tools/editor.js.map +1 -0
  88. package/dist/tools/engine.d.ts.map +1 -0
  89. package/dist/tools/engine.js.map +1 -0
  90. package/dist/tools/environment.d.ts.map +1 -0
  91. package/dist/tools/environment.js +2 -2
  92. package/dist/tools/environment.js.map +1 -0
  93. package/dist/tools/foliage.d.ts.map +1 -0
  94. package/dist/tools/foliage.js.map +1 -0
  95. package/dist/tools/handlers/actor-handlers.d.ts +1 -1
  96. package/dist/tools/handlers/actor-handlers.d.ts.map +1 -0
  97. package/dist/tools/handlers/actor-handlers.js +6 -5
  98. package/dist/tools/handlers/actor-handlers.js.map +1 -0
  99. package/dist/tools/handlers/animation-handlers.d.ts.map +1 -0
  100. package/dist/tools/handlers/animation-handlers.js.map +1 -0
  101. package/dist/tools/handlers/argument-helper.d.ts.map +1 -0
  102. package/dist/tools/handlers/argument-helper.js.map +1 -0
  103. package/dist/tools/handlers/asset-handlers.d.ts.map +1 -0
  104. package/dist/tools/handlers/asset-handlers.js +5 -1
  105. package/dist/tools/handlers/asset-handlers.js.map +1 -0
  106. package/dist/tools/handlers/audio-handlers.d.ts.map +1 -0
  107. package/dist/tools/handlers/audio-handlers.js.map +1 -0
  108. package/dist/tools/handlers/blueprint-handlers.d.ts.map +1 -0
  109. package/dist/tools/handlers/blueprint-handlers.js +2 -1
  110. package/dist/tools/handlers/blueprint-handlers.js.map +1 -0
  111. package/dist/tools/handlers/common-handlers.d.ts.map +1 -0
  112. package/dist/tools/handlers/common-handlers.js.map +1 -0
  113. package/dist/tools/handlers/editor-handlers.d.ts.map +1 -0
  114. package/dist/tools/handlers/editor-handlers.js +12 -2
  115. package/dist/tools/handlers/editor-handlers.js.map +1 -0
  116. package/dist/tools/handlers/effect-handlers.d.ts.map +1 -0
  117. package/dist/tools/handlers/effect-handlers.js.map +1 -0
  118. package/dist/tools/handlers/environment-handlers.d.ts.map +1 -0
  119. package/dist/tools/handlers/environment-handlers.js.map +1 -0
  120. package/dist/tools/handlers/graph-handlers.d.ts.map +1 -0
  121. package/dist/tools/handlers/graph-handlers.js +61 -1
  122. package/dist/tools/handlers/graph-handlers.js.map +1 -0
  123. package/dist/tools/handlers/input-handlers.d.ts.map +1 -0
  124. package/dist/tools/handlers/input-handlers.js.map +1 -0
  125. package/dist/tools/handlers/inspect-handlers.d.ts.map +1 -0
  126. package/dist/tools/handlers/inspect-handlers.js.map +1 -0
  127. package/dist/tools/handlers/level-handlers.d.ts.map +1 -0
  128. package/dist/tools/handlers/level-handlers.js.map +1 -0
  129. package/dist/tools/handlers/lighting-handlers.d.ts.map +1 -0
  130. package/dist/tools/handlers/lighting-handlers.js +23 -1
  131. package/dist/tools/handlers/lighting-handlers.js.map +1 -0
  132. package/dist/tools/handlers/performance-handlers.d.ts.map +1 -0
  133. package/dist/tools/handlers/performance-handlers.js +15 -2
  134. package/dist/tools/handlers/performance-handlers.js.map +1 -0
  135. package/dist/tools/handlers/pipeline-handlers.d.ts.map +1 -0
  136. package/dist/tools/handlers/pipeline-handlers.js.map +1 -0
  137. package/dist/tools/handlers/sequence-handlers.d.ts.map +1 -0
  138. package/dist/tools/handlers/sequence-handlers.js.map +1 -0
  139. package/dist/tools/handlers/system-handlers.d.ts.map +1 -0
  140. package/dist/tools/handlers/system-handlers.js +16 -1
  141. package/dist/tools/handlers/system-handlers.js.map +1 -0
  142. package/dist/tools/input.d.ts.map +1 -0
  143. package/dist/tools/input.js +3 -1
  144. package/dist/tools/input.js.map +1 -0
  145. package/dist/tools/introspection.d.ts.map +1 -0
  146. package/dist/tools/introspection.js.map +1 -0
  147. package/dist/tools/landscape.d.ts.map +1 -0
  148. package/dist/tools/landscape.js +3 -1
  149. package/dist/tools/landscape.js.map +1 -0
  150. package/dist/tools/level.d.ts.map +1 -0
  151. package/dist/tools/level.js.map +1 -0
  152. package/dist/tools/lighting.d.ts.map +1 -0
  153. package/dist/tools/lighting.js +3 -1
  154. package/dist/tools/lighting.js.map +1 -0
  155. package/dist/tools/logs.d.ts.map +1 -0
  156. package/dist/tools/logs.js.map +1 -0
  157. package/dist/tools/materials.d.ts.map +1 -0
  158. package/dist/tools/materials.js +3 -1
  159. package/dist/tools/materials.js.map +1 -0
  160. package/dist/tools/niagara.d.ts.map +1 -0
  161. package/dist/tools/niagara.js +7 -5
  162. package/dist/tools/niagara.js.map +1 -0
  163. package/dist/tools/performance.d.ts.map +1 -0
  164. package/dist/tools/performance.js.map +1 -0
  165. package/dist/tools/physics.d.ts.map +1 -0
  166. package/dist/tools/physics.js +9 -7
  167. package/dist/tools/physics.js.map +1 -0
  168. package/dist/tools/property-dictionary.d.ts.map +1 -0
  169. package/dist/tools/property-dictionary.js.map +1 -0
  170. package/dist/tools/sequence.d.ts.map +1 -0
  171. package/dist/tools/sequence.js +3 -1
  172. package/dist/tools/sequence.js.map +1 -0
  173. package/dist/tools/tool-definition-utils.d.ts.map +1 -0
  174. package/dist/tools/tool-definition-utils.js.map +1 -0
  175. package/dist/tools/ui.d.ts.map +1 -0
  176. package/dist/tools/ui.js +3 -1
  177. package/dist/tools/ui.js.map +1 -0
  178. package/dist/types/automation-responses.d.ts.map +1 -0
  179. package/dist/types/automation-responses.js.map +1 -0
  180. package/dist/types/env.d.ts.map +1 -0
  181. package/dist/types/env.js.map +1 -0
  182. package/dist/types/handler-types.d.ts.map +1 -0
  183. package/dist/types/handler-types.js.map +1 -0
  184. package/dist/types/tool-interfaces.d.ts.map +1 -0
  185. package/dist/types/tool-interfaces.js.map +1 -0
  186. package/dist/types/tool-types.d.ts.map +1 -0
  187. package/dist/types/tool-types.js.map +1 -0
  188. package/dist/unreal-bridge.d.ts +1 -0
  189. package/dist/unreal-bridge.d.ts.map +1 -0
  190. package/dist/unreal-bridge.js +8 -0
  191. package/dist/unreal-bridge.js.map +1 -0
  192. package/dist/utils/command-validator.d.ts.map +1 -0
  193. package/dist/utils/command-validator.js.map +1 -0
  194. package/dist/utils/elicitation.d.ts.map +1 -0
  195. package/dist/utils/elicitation.js.map +1 -0
  196. package/dist/utils/error-handler.d.ts.map +1 -0
  197. package/dist/utils/error-handler.js.map +1 -0
  198. package/dist/utils/ini-reader.d.ts.map +1 -0
  199. package/dist/utils/ini-reader.js.map +1 -0
  200. package/dist/utils/logger.d.ts.map +1 -0
  201. package/dist/utils/logger.js.map +1 -0
  202. package/dist/utils/normalize.d.ts.map +1 -0
  203. package/dist/utils/normalize.js.map +1 -0
  204. package/dist/utils/path-security.d.ts.map +1 -0
  205. package/dist/utils/path-security.js.map +1 -0
  206. package/dist/utils/response-factory.d.ts.map +1 -0
  207. package/dist/utils/response-factory.js +3 -1
  208. package/dist/utils/response-factory.js.map +1 -0
  209. package/dist/utils/response-validator.d.ts.map +1 -0
  210. package/dist/utils/response-validator.js.map +1 -0
  211. package/dist/utils/result-helpers.d.ts.map +1 -0
  212. package/dist/utils/result-helpers.js.map +1 -0
  213. package/dist/utils/safe-json.d.ts.map +1 -0
  214. package/dist/utils/safe-json.js.map +1 -0
  215. package/dist/utils/unreal-command-queue.d.ts.map +1 -0
  216. package/dist/utils/unreal-command-queue.js.map +1 -0
  217. package/dist/utils/validation.d.ts.map +1 -0
  218. package/dist/utils/validation.js.map +1 -0
  219. package/dist/wasm/index.d.ts.map +1 -0
  220. package/dist/wasm/index.js.map +1 -0
  221. package/package.json +12 -34
  222. package/server.json +2 -2
  223. package/.dockerignore +0 -57
  224. package/.env.example +0 -26
  225. package/.env.production +0 -61
  226. package/.eslintrc.json +0 -0
  227. package/.eslintrc.override.json +0 -8
  228. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -94
  229. package/.github/ISSUE_TEMPLATE/config.yml +0 -8
  230. package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -56
  231. package/.github/copilot-instructions.md +0 -478
  232. package/.github/dependabot.yml +0 -19
  233. package/.github/labeler.yml +0 -24
  234. package/.github/labels.yml +0 -70
  235. package/.github/pull_request_template.md +0 -42
  236. package/.github/release-drafter-config.yml +0 -51
  237. package/.github/workflows/auto-merge.yml +0 -38
  238. package/.github/workflows/ci.yml +0 -38
  239. package/.github/workflows/dependency-review.yml +0 -17
  240. package/.github/workflows/gemini-issue-triage.yml +0 -172
  241. package/.github/workflows/greetings.yml +0 -27
  242. package/.github/workflows/labeler.yml +0 -17
  243. package/.github/workflows/links.yml +0 -80
  244. package/.github/workflows/pr-size-labeler.yml +0 -137
  245. package/.github/workflows/publish-mcp.yml +0 -79
  246. package/.github/workflows/release-drafter.yml +0 -24
  247. package/.github/workflows/release.yml +0 -112
  248. package/.github/workflows/semantic-pull-request.yml +0 -35
  249. package/.github/workflows/smoke-test.yml +0 -36
  250. package/.github/workflows/stale.yml +0 -28
  251. package/CONTRIBUTING.md +0 -140
  252. package/Dockerfile +0 -37
  253. package/GEMINI.md +0 -115
  254. package/Public/Plugin_setup_guide.mp4 +0 -0
  255. package/Public/icon.png +0 -0
  256. package/claude_desktop_config_example.json +0 -15
  257. package/dist/types/responses.d.ts +0 -249
  258. package/dist/types/responses.js +0 -2
  259. package/docs/GraphQL-API.md +0 -888
  260. package/docs/Migration-Guide-v0.5.0.md +0 -684
  261. package/docs/Roadmap.md +0 -53
  262. package/docs/WebAssembly-Integration.md +0 -628
  263. package/docs/editor-plugin-extension.md +0 -370
  264. package/docs/handler-mapping.md +0 -249
  265. package/docs/native-automation-progress.md +0 -128
  266. package/docs/testing-guide.md +0 -423
  267. package/eslint.config.mjs +0 -68
  268. package/mcp-config-example.json +0 -14
  269. package/plugins/McpAutomationBridge/Config/FilterPlugin.ini +0 -8
  270. package/plugins/McpAutomationBridge/McpAutomationBridge.uplugin +0 -64
  271. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/McpAutomationBridge.Build.cs +0 -189
  272. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.cpp +0 -22
  273. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.h +0 -30
  274. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeHelpers.h +0 -1983
  275. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeModule.cpp +0 -72
  276. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSettings.cpp +0 -46
  277. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSubsystem.cpp +0 -846
  278. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AnimationHandlers.cpp +0 -2393
  279. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetQueryHandlers.cpp +0 -300
  280. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetWorkflowHandlers.cpp +0 -2807
  281. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AudioHandlers.cpp +0 -1087
  282. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BehaviorTreeHandlers.cpp +0 -488
  283. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.cpp +0 -643
  284. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.h +0 -31
  285. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintGraphHandlers.cpp +0 -1094
  286. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers.cpp +0 -5750
  287. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers_List.cpp +0 -152
  288. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ControlHandlers.cpp +0 -2614
  289. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_DebugHandlers.cpp +0 -42
  290. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EditorFunctionHandlers.cpp +0 -1237
  291. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EffectHandlers.cpp +0 -1725
  292. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EnvironmentHandlers.cpp +0 -2265
  293. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_FoliageHandlers.cpp +0 -954
  294. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InputHandlers.cpp +0 -209
  295. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InsightsHandlers.cpp +0 -41
  296. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LandscapeHandlers.cpp +0 -1164
  297. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LevelHandlers.cpp +0 -762
  298. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LightingHandlers.cpp +0 -663
  299. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LogHandlers.cpp +0 -136
  300. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_MaterialGraphHandlers.cpp +0 -494
  301. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraGraphHandlers.cpp +0 -278
  302. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraHandlers.cpp +0 -625
  303. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PerformanceHandlers.cpp +0 -401
  304. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PipelineHandlers.cpp +0 -67
  305. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ProcessRequest.cpp +0 -472
  306. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PropertyHandlers.cpp +0 -2634
  307. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_RenderHandlers.cpp +0 -189
  308. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.cpp +0 -917
  309. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.h +0 -39
  310. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequenceHandlers.cpp +0 -2706
  311. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequencerHandlers.cpp +0 -519
  312. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_TestHandlers.cpp +0 -38
  313. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_UiHandlers.cpp +0 -668
  314. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_WorldPartitionHandlers.cpp +0 -346
  315. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.cpp +0 -1345
  316. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.h +0 -149
  317. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpConnectionManager.cpp +0 -782
  318. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSettings.h +0 -115
  319. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSubsystem.h +0 -796
  320. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpConnectionManager.h +0 -117
  321. package/scripts/check-unreal-connection.mjs +0 -19
  322. package/scripts/clean-tmp.js +0 -23
  323. package/scripts/patch-wasm.js +0 -26
  324. package/scripts/run-all-tests.mjs +0 -136
  325. package/scripts/smoke-test.ts +0 -94
  326. package/scripts/sync-mcp-plugin.js +0 -143
  327. package/scripts/test-no-plugin-alternates.mjs +0 -113
  328. package/scripts/validate-server.js +0 -46
  329. package/scripts/verify-automation-bridge.js +0 -200
  330. package/src/automation/bridge.ts +0 -630
  331. package/src/automation/connection-manager.ts +0 -148
  332. package/src/automation/handshake.ts +0 -99
  333. package/src/automation/index.ts +0 -2
  334. package/src/automation/message-handler.ts +0 -192
  335. package/src/automation/request-tracker.ts +0 -155
  336. package/src/automation/types.ts +0 -108
  337. package/src/cli.ts +0 -34
  338. package/src/config/class-aliases.ts +0 -65
  339. package/src/config.ts +0 -73
  340. package/src/constants.ts +0 -29
  341. package/src/graphql/loaders.ts +0 -244
  342. package/src/graphql/resolvers.ts +0 -1008
  343. package/src/graphql/schema.ts +0 -452
  344. package/src/graphql/server.ts +0 -156
  345. package/src/graphql/types.ts +0 -10
  346. package/src/handlers/resource-handlers.ts +0 -186
  347. package/src/index.ts +0 -243
  348. package/src/resources/actors.ts +0 -127
  349. package/src/resources/assets.ts +0 -286
  350. package/src/resources/levels.ts +0 -68
  351. package/src/server/resource-registry.ts +0 -47
  352. package/src/server/tool-registry.ts +0 -354
  353. package/src/server-setup.ts +0 -114
  354. package/src/services/health-monitor.ts +0 -132
  355. package/src/services/metrics-server.ts +0 -176
  356. package/src/tools/actors.ts +0 -564
  357. package/src/tools/animation.ts +0 -941
  358. package/src/tools/assets.ts +0 -394
  359. package/src/tools/audio.ts +0 -499
  360. package/src/tools/base-tool.ts +0 -52
  361. package/src/tools/behavior-tree.ts +0 -45
  362. package/src/tools/blueprint.ts +0 -940
  363. package/src/tools/consolidated-tool-definitions.ts +0 -1256
  364. package/src/tools/consolidated-tool-handlers.ts +0 -302
  365. package/src/tools/debug.ts +0 -622
  366. package/src/tools/dynamic-handler-registry.ts +0 -33
  367. package/src/tools/editor.ts +0 -435
  368. package/src/tools/engine.ts +0 -43
  369. package/src/tools/environment.ts +0 -281
  370. package/src/tools/foliage.ts +0 -596
  371. package/src/tools/handlers/actor-handlers.ts +0 -244
  372. package/src/tools/handlers/animation-handlers.ts +0 -237
  373. package/src/tools/handlers/argument-helper.ts +0 -142
  374. package/src/tools/handlers/asset-handlers.ts +0 -550
  375. package/src/tools/handlers/audio-handlers.ts +0 -194
  376. package/src/tools/handlers/blueprint-handlers.ts +0 -380
  377. package/src/tools/handlers/common-handlers.ts +0 -108
  378. package/src/tools/handlers/editor-handlers.ts +0 -124
  379. package/src/tools/handlers/effect-handlers.ts +0 -224
  380. package/src/tools/handlers/environment-handlers.ts +0 -183
  381. package/src/tools/handlers/graph-handlers.ts +0 -117
  382. package/src/tools/handlers/input-handlers.ts +0 -28
  383. package/src/tools/handlers/inspect-handlers.ts +0 -450
  384. package/src/tools/handlers/level-handlers.ts +0 -253
  385. package/src/tools/handlers/lighting-handlers.ts +0 -151
  386. package/src/tools/handlers/performance-handlers.ts +0 -132
  387. package/src/tools/handlers/pipeline-handlers.ts +0 -194
  388. package/src/tools/handlers/sequence-handlers.ts +0 -438
  389. package/src/tools/handlers/system-handlers.ts +0 -564
  390. package/src/tools/input.ts +0 -160
  391. package/src/tools/introspection.ts +0 -689
  392. package/src/tools/landscape.ts +0 -649
  393. package/src/tools/level.ts +0 -989
  394. package/src/tools/lighting.ts +0 -1052
  395. package/src/tools/logs.ts +0 -219
  396. package/src/tools/materials.ts +0 -295
  397. package/src/tools/niagara.ts +0 -485
  398. package/src/tools/performance.ts +0 -661
  399. package/src/tools/physics.ts +0 -679
  400. package/src/tools/property-dictionary.ts +0 -98
  401. package/src/tools/sequence.ts +0 -385
  402. package/src/tools/tool-definition-utils.ts +0 -35
  403. package/src/tools/ui.ts +0 -452
  404. package/src/types/automation-responses.ts +0 -119
  405. package/src/types/env.ts +0 -17
  406. package/src/types/handler-types.ts +0 -442
  407. package/src/types/responses.ts +0 -355
  408. package/src/types/tool-interfaces.ts +0 -250
  409. package/src/types/tool-types.ts +0 -575
  410. package/src/unreal-bridge.ts +0 -693
  411. package/src/utils/command-validator.ts +0 -139
  412. package/src/utils/elicitation.ts +0 -132
  413. package/src/utils/error-handler.ts +0 -287
  414. package/src/utils/ini-reader.ts +0 -86
  415. package/src/utils/logger.ts +0 -35
  416. package/src/utils/normalize.test.ts +0 -162
  417. package/src/utils/normalize.ts +0 -146
  418. package/src/utils/path-security.ts +0 -43
  419. package/src/utils/response-factory.ts +0 -44
  420. package/src/utils/response-validator.ts +0 -395
  421. package/src/utils/result-helpers.ts +0 -195
  422. package/src/utils/safe-json.test.ts +0 -90
  423. package/src/utils/safe-json.ts +0 -70
  424. package/src/utils/unreal-command-queue.ts +0 -166
  425. package/src/utils/validation.test.ts +0 -184
  426. package/src/utils/validation.ts +0 -312
  427. package/src/wasm/index.ts +0 -838
  428. package/test-server.mjs +0 -100
  429. package/tests/test-animation.mjs +0 -369
  430. package/tests/test-asset-advanced.mjs +0 -82
  431. package/tests/test-asset-graph.mjs +0 -311
  432. package/tests/test-audio.mjs +0 -417
  433. package/tests/test-automation-timeouts.mjs +0 -98
  434. package/tests/test-behavior-tree.mjs +0 -444
  435. package/tests/test-blueprint-graph.mjs +0 -410
  436. package/tests/test-blueprint.mjs +0 -577
  437. package/tests/test-client-mode.mjs +0 -86
  438. package/tests/test-console-command.mjs +0 -56
  439. package/tests/test-control-actor.mjs +0 -425
  440. package/tests/test-control-editor.mjs +0 -112
  441. package/tests/test-graphql.mjs +0 -372
  442. package/tests/test-input.mjs +0 -349
  443. package/tests/test-inspect.mjs +0 -302
  444. package/tests/test-landscape.mjs +0 -316
  445. package/tests/test-lighting.mjs +0 -428
  446. package/tests/test-manage-asset.mjs +0 -438
  447. package/tests/test-manage-level.mjs +0 -89
  448. package/tests/test-materials.mjs +0 -356
  449. package/tests/test-niagara.mjs +0 -185
  450. package/tests/test-no-inline-python.mjs +0 -122
  451. package/tests/test-performance.mjs +0 -539
  452. package/tests/test-plugin-handshake.mjs +0 -82
  453. package/tests/test-runner.mjs +0 -993
  454. package/tests/test-sequence.mjs +0 -104
  455. package/tests/test-system.mjs +0 -96
  456. package/tests/test-wasm.mjs +0 -283
  457. package/tests/test-world-partition.mjs +0 -215
  458. package/tsconfig.json +0 -56
  459. package/vitest.config.ts +0 -35
  460. package/wasm/Cargo.lock +0 -363
  461. package/wasm/Cargo.toml +0 -42
  462. package/wasm/LICENSE +0 -21
  463. package/wasm/README.md +0 -253
  464. package/wasm/src/dependency_resolver.rs +0 -377
  465. package/wasm/src/lib.rs +0 -153
  466. package/wasm/src/property_parser.rs +0 -271
  467. package/wasm/src/transform_math.rs +0 -396
  468. package/wasm/tests/integration.rs +0 -109
@@ -1,630 +0,0 @@
1
- import { EventEmitter } from 'node:events';
2
- import { WebSocket } from 'ws';
3
- import { Logger } from '../utils/logger.js';
4
- import {
5
- DEFAULT_AUTOMATION_HOST,
6
- DEFAULT_AUTOMATION_PORT,
7
- DEFAULT_NEGOTIATED_PROTOCOLS,
8
- DEFAULT_HEARTBEAT_INTERVAL_MS,
9
- DEFAULT_MAX_PENDING_REQUESTS,
10
- DEFAULT_MAX_QUEUED_REQUESTS,
11
- MAX_WS_MESSAGE_SIZE_BYTES
12
- } from '../constants.js';
13
- import { createRequire } from 'node:module';
14
- import {
15
- AutomationBridgeOptions,
16
- AutomationBridgeStatus,
17
- AutomationBridgeMessage,
18
- AutomationBridgeResponseMessage,
19
- AutomationBridgeEvents
20
- } from './types.js';
21
- import { ConnectionManager } from './connection-manager.js';
22
- import { RequestTracker } from './request-tracker.js';
23
- import { HandshakeHandler } from './handshake.js';
24
- import { MessageHandler } from './message-handler.js';
25
-
26
- const require = createRequire(import.meta.url);
27
- const packageInfo: { name?: string; version?: string } = (() => {
28
- try {
29
- return require('../../package.json');
30
- } catch (error) {
31
- const log = new Logger('AutomationBridge');
32
- log.debug('Unable to read package.json for version info', error);
33
- return {};
34
- }
35
- })();
36
-
37
- export class AutomationBridge extends EventEmitter {
38
- private readonly host: string;
39
- private readonly port: number;
40
- private readonly ports: number[];
41
- private readonly negotiatedProtocols: string[];
42
- private readonly capabilityToken?: string;
43
- private readonly enabled: boolean;
44
- private readonly serverName: string;
45
- private readonly serverVersion: string;
46
- private readonly clientHost: string;
47
- private readonly clientPort: number;
48
- private readonly serverLegacyEnabled: boolean;
49
- private readonly maxConcurrentConnections: number;
50
- private readonly maxQueuedRequests: number;
51
-
52
- private connectionManager: ConnectionManager;
53
- private requestTracker: RequestTracker;
54
- private handshakeHandler: HandshakeHandler;
55
- private messageHandler: MessageHandler;
56
- private log = new Logger('AutomationBridge');
57
-
58
- private lastHandshakeAt?: Date;
59
- private lastHandshakeMetadata?: Record<string, unknown>;
60
- private lastHandshakeAck?: AutomationBridgeMessage;
61
- private lastHandshakeFailure?: { reason: string; at: Date };
62
- private lastDisconnect?: { code: number; reason: string; at: Date };
63
- private lastError?: { message: string; at: Date };
64
- private queuedRequestItems: Array<{ resolve: (v: any) => void; reject: (e: any) => void; action: string; payload: any; options: any }> = [];
65
- private connectionPromise?: Promise<void>;
66
- private connectionLock = false;
67
-
68
- constructor(options: AutomationBridgeOptions = {}) {
69
- super();
70
- this.host = options.host ?? process.env.MCP_AUTOMATION_WS_HOST ?? DEFAULT_AUTOMATION_HOST;
71
-
72
- const sanitizePort = (value: unknown): number | null => {
73
- if (typeof value === 'number' && Number.isInteger(value)) {
74
- return value > 0 && value <= 65535 ? value : null;
75
- }
76
- if (typeof value === 'string' && value.trim().length > 0) {
77
- const parsed = Number.parseInt(value.trim(), 10);
78
- return Number.isInteger(parsed) && parsed > 0 && parsed <= 65535 ? parsed : null;
79
- }
80
- return null;
81
- };
82
-
83
- const defaultPort = sanitizePort(options.port ?? process.env.MCP_AUTOMATION_WS_PORT) ?? DEFAULT_AUTOMATION_PORT;
84
- const configuredPortValues: Array<number | string> | undefined = options.ports
85
- ? options.ports
86
- : process.env.MCP_AUTOMATION_WS_PORTS
87
- ?.split(',')
88
- .map((token) => token.trim())
89
- .filter((token) => token.length > 0);
90
-
91
- const sanitizedPorts = Array.isArray(configuredPortValues)
92
- ? configuredPortValues
93
- .map((value) => sanitizePort(value))
94
- .filter((port): port is number => port !== null)
95
- : [];
96
-
97
- if (!sanitizedPorts.includes(defaultPort)) {
98
- sanitizedPorts.unshift(defaultPort);
99
- }
100
- if (sanitizedPorts.length === 0) {
101
- sanitizedPorts.push(DEFAULT_AUTOMATION_PORT);
102
- }
103
-
104
- this.ports = Array.from(new Set(sanitizedPorts));
105
- const defaultProtocols = DEFAULT_NEGOTIATED_PROTOCOLS;
106
- const userProtocols = Array.isArray(options.protocols)
107
- ? options.protocols.filter((proto) => typeof proto === 'string' && proto.trim().length > 0)
108
- : [];
109
- const envProtocols = process.env.MCP_AUTOMATION_WS_PROTOCOLS
110
- ? process.env.MCP_AUTOMATION_WS_PROTOCOLS.split(',')
111
- .map((token) => token.trim())
112
- .filter((token) => token.length > 0)
113
- : [];
114
- this.negotiatedProtocols = Array.from(new Set([...userProtocols, ...envProtocols, ...defaultProtocols]));
115
- this.port = this.ports[0];
116
- this.serverLegacyEnabled =
117
- options.serverLegacyEnabled ?? process.env.MCP_AUTOMATION_SERVER_LEGACY !== 'false';
118
- this.capabilityToken =
119
- options.capabilityToken ?? process.env.MCP_AUTOMATION_CAPABILITY_TOKEN ?? undefined;
120
- this.enabled = options.enabled ?? process.env.MCP_AUTOMATION_BRIDGE_ENABLED !== 'false';
121
- this.serverName = options.serverName
122
- ?? process.env.MCP_SERVER_NAME
123
- ?? packageInfo.name
124
- ?? 'unreal-engine-mcp';
125
- this.serverVersion = options.serverVersion
126
- ?? process.env.MCP_SERVER_VERSION
127
- ?? packageInfo.version
128
- ?? process.env.npm_package_version
129
- ?? '0.0.0';
130
-
131
- const heartbeatIntervalMs = (options.heartbeatIntervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS) > 0
132
- ? (options.heartbeatIntervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS)
133
- : 0;
134
-
135
- const maxPendingRequests = Math.max(1, options.maxPendingRequests ?? DEFAULT_MAX_PENDING_REQUESTS);
136
- const maxConcurrentConnections = Math.max(1, options.maxConcurrentConnections ?? 10);
137
- this.maxQueuedRequests = Math.max(0, options.maxQueuedRequests ?? DEFAULT_MAX_QUEUED_REQUESTS);
138
-
139
- this.clientHost = options.clientHost ?? process.env.MCP_AUTOMATION_CLIENT_HOST ?? DEFAULT_AUTOMATION_HOST;
140
- this.clientPort = options.clientPort ?? sanitizePort(process.env.MCP_AUTOMATION_CLIENT_PORT) ?? DEFAULT_AUTOMATION_PORT;
141
- this.maxConcurrentConnections = maxConcurrentConnections;
142
-
143
- // Initialize components
144
- this.connectionManager = new ConnectionManager(heartbeatIntervalMs);
145
- this.requestTracker = new RequestTracker(maxPendingRequests);
146
- this.handshakeHandler = new HandshakeHandler(this.capabilityToken);
147
- this.messageHandler = new MessageHandler(this.requestTracker);
148
-
149
- // Forward events from connection manager
150
- // Note: ConnectionManager doesn't emit 'connected'/'disconnected' directly in the same way,
151
- // we handle socket events here and use ConnectionManager to track state.
152
- }
153
-
154
- override on<K extends keyof AutomationBridgeEvents>(
155
- event: K,
156
- listener: AutomationBridgeEvents[K]
157
- ): this {
158
- return super.on(event, listener as (...args: unknown[]) => void);
159
- }
160
-
161
- override once<K extends keyof AutomationBridgeEvents>(
162
- event: K,
163
- listener: AutomationBridgeEvents[K]
164
- ): this {
165
- return super.once(event, listener as (...args: unknown[]) => void);
166
- }
167
-
168
- override off<K extends keyof AutomationBridgeEvents>(
169
- event: K,
170
- listener: AutomationBridgeEvents[K]
171
- ): this {
172
- return super.off(event, listener as (...args: unknown[]) => void);
173
- }
174
-
175
- start(): void {
176
- if (!this.enabled) {
177
- this.log.info('Automation bridge disabled by configuration.');
178
- return;
179
- }
180
-
181
- this.log.info(`Automation bridge connecting to Unreal server at ws://${this.clientHost}:${this.clientPort}`);
182
- this.startClient();
183
- }
184
-
185
- private startClient(): void {
186
- try {
187
- const url = `ws://${this.clientHost}:${this.clientPort}`;
188
- this.log.info(`Connecting to Unreal Engine automation server at ${url}`);
189
-
190
- this.log.debug(`Negotiated protocols: ${JSON.stringify(this.negotiatedProtocols)}`);
191
-
192
- const protocols = this.negotiatedProtocols.length === 1
193
- ? this.negotiatedProtocols[0]
194
- : this.negotiatedProtocols;
195
-
196
- this.log.debug(`Using WebSocket protocols arg: ${JSON.stringify(protocols)}`);
197
-
198
- const headers: Record<string, string> | undefined = this.capabilityToken
199
- ? {
200
- 'X-MCP-Capability': this.capabilityToken,
201
- 'X-MCP-Capability-Token': this.capabilityToken
202
- }
203
- : undefined;
204
-
205
- const socket = new WebSocket(url, protocols, {
206
- headers,
207
- perMessageDeflate: false
208
- });
209
-
210
- this.handleClientConnection(socket);
211
- } catch (error) {
212
- const errorObj = error instanceof Error ? error : new Error(String(error));
213
- this.lastError = { message: errorObj.message, at: new Date() };
214
- this.log.error('Failed to create WebSocket client connection', errorObj);
215
- const errorWithPort = Object.assign(errorObj, { port: this.clientPort });
216
- this.emitAutomation('error', errorWithPort);
217
- }
218
- }
219
-
220
- private async handleClientConnection(socket: WebSocket): Promise<void> {
221
- socket.on('open', async () => {
222
- this.log.info('Automation bridge client connected, starting handshake');
223
- try {
224
- const metadata = await this.handshakeHandler.initiateHandshake(socket);
225
-
226
- this.lastHandshakeAt = new Date();
227
- this.lastHandshakeMetadata = metadata;
228
- this.lastHandshakeFailure = undefined;
229
- this.connectionManager.updateLastMessageTime();
230
-
231
- // Extract remote address/port from underlying TCP socket
232
- // Note: WebSocket types don't expose _socket, but it exists at runtime
233
- const socketWithInternal = socket as unknown as { _socket?: { remoteAddress?: string; remotePort?: number }; socket?: { remoteAddress?: string; remotePort?: number } };
234
- const underlying = socketWithInternal._socket || socketWithInternal.socket;
235
- const remoteAddr = underlying?.remoteAddress ?? undefined;
236
- const remotePort = underlying?.remotePort ?? undefined;
237
-
238
- this.connectionManager.registerSocket(socket, this.clientPort, metadata, remoteAddr, remotePort);
239
- this.connectionManager.startHeartbeat();
240
-
241
- this.emitAutomation('connected', {
242
- socket,
243
- metadata,
244
- port: this.clientPort,
245
- protocol: socket.protocol || null
246
- });
247
-
248
- const getRawDataByteLength = (data: unknown): number => {
249
- if (typeof data === 'string') {
250
- return Buffer.byteLength(data, 'utf8');
251
- }
252
-
253
- if (Buffer.isBuffer(data)) {
254
- return data.length;
255
- }
256
-
257
- if (Array.isArray(data)) {
258
- return data.reduce((total, item) => total + (Buffer.isBuffer(item) ? item.length : 0), 0);
259
- }
260
-
261
- if (data instanceof ArrayBuffer) {
262
- return data.byteLength;
263
- }
264
-
265
- if (ArrayBuffer.isView(data)) {
266
- return data.byteLength;
267
- }
268
-
269
- return 0;
270
- };
271
-
272
- const rawDataToUtf8String = (data: unknown, byteLengthHint?: number): string => {
273
- if (typeof data === 'string') {
274
- return data;
275
- }
276
-
277
- if (Buffer.isBuffer(data)) {
278
- return data.toString('utf8');
279
- }
280
-
281
- if (Array.isArray(data)) {
282
- const buffers = data.filter((item): item is Buffer => Buffer.isBuffer(item));
283
- const totalLength = typeof byteLengthHint === 'number'
284
- ? byteLengthHint
285
- : buffers.reduce((total, item) => total + item.length, 0);
286
- return Buffer.concat(buffers, totalLength).toString('utf8');
287
- }
288
-
289
- if (data instanceof ArrayBuffer) {
290
- return Buffer.from(data).toString('utf8');
291
- }
292
-
293
- if (ArrayBuffer.isView(data)) {
294
- return Buffer.from(data.buffer, data.byteOffset, data.byteLength).toString('utf8');
295
- }
296
-
297
- return '';
298
- };
299
-
300
- socket.on('message', (data) => {
301
- try {
302
- const byteLength = getRawDataByteLength(data);
303
- if (byteLength > MAX_WS_MESSAGE_SIZE_BYTES) {
304
- this.log.error(
305
- `Received oversized message (${byteLength} bytes, max: ${MAX_WS_MESSAGE_SIZE_BYTES}). Dropping.`
306
- );
307
- return;
308
- }
309
-
310
- const text = rawDataToUtf8String(data, byteLength);
311
- this.log.debug(`[AutomationBridge Client] Received message: ${text.substring(0, 1000)}`);
312
- const parsed = JSON.parse(text) as AutomationBridgeMessage;
313
- this.connectionManager.updateLastMessageTime();
314
- this.messageHandler.handleMessage(parsed);
315
- this.emitAutomation('message', parsed);
316
- } catch (error) {
317
- this.log.error('Error handling message', error);
318
- }
319
- });
320
-
321
- } catch (error) {
322
- const err = error instanceof Error ? error : new Error(String(error));
323
- this.lastHandshakeFailure = { reason: err.message, at: new Date() };
324
- this.emitAutomation('handshakeFailed', { reason: err.message, port: this.clientPort });
325
- }
326
- });
327
-
328
- socket.on('error', (error) => {
329
- this.log.error('Automation bridge client socket error', error);
330
- const errObj = error instanceof Error ? error : new Error(String(error));
331
- this.lastError = { message: errObj.message, at: new Date() };
332
- const errWithPort = Object.assign(errObj, { port: this.clientPort });
333
- this.emitAutomation('error', errWithPort);
334
- });
335
-
336
- socket.on('close', (code, reasonBuffer) => {
337
- const reason = reasonBuffer.toString('utf8');
338
- const socketInfo = this.connectionManager.removeSocket(socket);
339
-
340
- if (socketInfo) {
341
- this.lastDisconnect = { code, reason, at: new Date() };
342
- this.emitAutomation('disconnected', {
343
- code,
344
- reason,
345
- port: socketInfo.port,
346
- protocol: socketInfo.protocol || null
347
- });
348
- this.log.info(`Automation bridge client socket closed (code=${code}, reason=${reason})`);
349
-
350
- if (!this.connectionManager.isConnected()) {
351
- this.requestTracker.rejectAll(new Error(reason || 'Connection lost'));
352
- }
353
- }
354
- });
355
- }
356
-
357
- stop(): void {
358
- if (this.isConnected()) {
359
- this.broadcast({
360
- type: 'bridge_shutdown',
361
- timestamp: new Date().toISOString(),
362
- reason: 'Server shutting down'
363
- });
364
- }
365
- this.connectionManager.closeAll(1001, 'Server shutdown');
366
- this.lastHandshakeAck = undefined;
367
- this.requestTracker.rejectAll(new Error('Automation bridge server stopped'));
368
- }
369
-
370
- isConnected(): boolean {
371
- return this.connectionManager.isConnected();
372
- }
373
-
374
- getStatus(): AutomationBridgeStatus {
375
-
376
- const connectionInfos = Array.from(this.connectionManager.getActiveSockets().entries()).map(([socket, info]) => ({
377
- connectionId: info.connectionId,
378
- sessionId: info.sessionId ?? null,
379
- remoteAddress: info.remoteAddress ?? null,
380
- remotePort: info.remotePort ?? null,
381
- port: info.port,
382
- connectedAt: info.connectedAt.toISOString(),
383
- protocol: info.protocol || null,
384
- readyState: socket.readyState,
385
- isPrimary: socket === this.connectionManager.getPrimarySocket()
386
- }));
387
-
388
- return {
389
- enabled: this.enabled,
390
- host: this.host,
391
- port: this.port,
392
- configuredPorts: [...this.ports],
393
- listeningPorts: [], // We are client-only now
394
- connected: this.isConnected(),
395
- connectedAt: connectionInfos.length > 0 ? connectionInfos[0].connectedAt : null,
396
- activePort: connectionInfos.length > 0 ? connectionInfos[0].port : null,
397
- negotiatedProtocol: connectionInfos.length > 0 ? connectionInfos[0].protocol : null,
398
- supportedProtocols: [...this.negotiatedProtocols],
399
- supportedOpcodes: ['automation_request'],
400
- expectedResponseOpcodes: ['automation_response'],
401
- capabilityTokenRequired: Boolean(this.capabilityToken),
402
- lastHandshakeAt: this.lastHandshakeAt?.toISOString() ?? null,
403
- lastHandshakeMetadata: this.lastHandshakeMetadata ?? null,
404
- lastHandshakeAck: this.lastHandshakeAck ?? null,
405
- lastHandshakeFailure: this.lastHandshakeFailure
406
- ? { reason: this.lastHandshakeFailure.reason, at: this.lastHandshakeFailure.at.toISOString() }
407
- : null,
408
- lastDisconnect: this.lastDisconnect
409
- ? { code: this.lastDisconnect.code, reason: this.lastDisconnect.reason, at: this.lastDisconnect.at.toISOString() }
410
- : null,
411
- lastError: this.lastError
412
- ? { message: this.lastError.message, at: this.lastError.at.toISOString() }
413
- : null,
414
- lastMessageAt: this.connectionManager.getLastMessageTime()?.toISOString() ?? null,
415
- lastRequestSentAt: this.requestTracker.getLastRequestSentAt()?.toISOString() ?? null,
416
- pendingRequests: this.requestTracker.getPendingCount(),
417
- pendingRequestDetails: this.requestTracker.getPendingDetails(),
418
- connections: connectionInfos,
419
- webSocketListening: false,
420
- serverLegacyEnabled: this.serverLegacyEnabled,
421
- serverName: this.serverName,
422
- serverVersion: this.serverVersion,
423
- maxConcurrentConnections: this.maxConcurrentConnections,
424
- maxPendingRequests: this.requestTracker.getMaxPendingRequests(),
425
- heartbeatIntervalMs: this.connectionManager.getHeartbeatIntervalMs()
426
- };
427
- }
428
-
429
- async sendAutomationRequest<T = AutomationBridgeResponseMessage>(
430
- action: string,
431
- payload: Record<string, unknown> = {},
432
- options: { timeoutMs?: number } = {}
433
- ): Promise<T> {
434
- if (!this.isConnected()) {
435
- if (this.enabled) {
436
- this.log.info('Automation bridge not connected, attempting lazy connection...');
437
-
438
- // Avoid multiple simultaneous connection attempts using lock
439
- if (!this.connectionPromise && !this.connectionLock) {
440
- this.connectionLock = true;
441
- this.connectionPromise = new Promise<void>((resolve, reject) => {
442
- const onConnect = () => {
443
- cleanup(); resolve();
444
- };
445
- // We map errors to rejects, but we should be careful about which errors.
446
- // A socket error might happen during connection.
447
- const onError = (err: any) => {
448
- cleanup(); reject(err);
449
- };
450
- // Also listen for handshake failure
451
- const onHandshakeFail = (err: any) => {
452
- cleanup(); reject(new Error(`Handshake failed: ${err.reason}`));
453
- };
454
-
455
- const cleanup = () => {
456
- this.off('connected', onConnect);
457
- this.off('error', onError);
458
- this.off('handshakeFailed', onHandshakeFail);
459
- // Clear lock and promise so next attempt can try again
460
- this.connectionLock = false;
461
- this.connectionPromise = undefined;
462
- };
463
-
464
- this.once('connected', onConnect);
465
- this.once('error', onError);
466
- this.once('handshakeFailed', onHandshakeFail);
467
-
468
- try {
469
- this.startClient();
470
- } catch (e) {
471
- onError(e);
472
- }
473
- });
474
- }
475
-
476
- try {
477
- // Wait for connection with a short timeout for the connection itself
478
- const connectTimeout = 5000;
479
- let timeoutId: ReturnType<typeof setTimeout> | undefined;
480
- const timeoutPromise = new Promise<never>((_, reject) => {
481
- timeoutId = setTimeout(() => reject(new Error('Lazy connection timeout')), connectTimeout);
482
- });
483
-
484
- try {
485
- await Promise.race([this.connectionPromise, timeoutPromise]);
486
- } finally {
487
- if (timeoutId) clearTimeout(timeoutId);
488
- }
489
- } catch (err: any) {
490
- this.log.error('Lazy connection failed', err);
491
- // We don't throw here immediately, we let the isConnected check fail below
492
- // or throw a specific error.
493
- // Actually, if connection failed, we should probably fail the request.
494
- throw new Error(`Failed to establish connection to Unreal Engine: ${err.message}`);
495
- }
496
- } else {
497
- throw new Error('Automation bridge disabled');
498
- }
499
- }
500
-
501
- if (!this.isConnected()) {
502
- throw new Error('Automation bridge not connected');
503
- }
504
-
505
- if (this.requestTracker.getPendingCount() >= this.requestTracker.getMaxPendingRequests()) {
506
- if (this.queuedRequestItems.length >= this.maxQueuedRequests) {
507
- throw new Error(`Automation bridge request queue is full (max: ${this.maxQueuedRequests}). Please retry later.`);
508
- }
509
- return new Promise<T>((resolve, reject) => {
510
- this.queuedRequestItems.push({
511
- resolve,
512
- reject,
513
- action,
514
- payload,
515
- options
516
- });
517
- });
518
- }
519
-
520
- return this.sendRequestInternal<T>(action, payload, options);
521
- }
522
-
523
- private async sendRequestInternal<T>(
524
- action: string,
525
- payload: Record<string, unknown>,
526
- options: { timeoutMs?: number }
527
- ): Promise<T> {
528
- const timeoutMs = options.timeoutMs ?? 60000; // Increased default timeout to 60s
529
-
530
- // Check for coalescing
531
- const coalesceKey = this.requestTracker.createCoalesceKey(action, payload);
532
- if (coalesceKey) {
533
- const existing = this.requestTracker.getCoalescedRequest(coalesceKey);
534
- if (existing) {
535
- return existing as unknown as T;
536
- }
537
- }
538
-
539
- const { requestId, promise } = this.requestTracker.createRequest(action, payload, timeoutMs);
540
-
541
- if (coalesceKey) {
542
- this.requestTracker.setCoalescedRequest(coalesceKey, promise);
543
- }
544
-
545
- const message: AutomationBridgeMessage = {
546
- type: 'automation_request',
547
- requestId,
548
- action,
549
- payload
550
- };
551
-
552
- const resultPromise = promise as unknown as Promise<T>;
553
-
554
- // Ensure we process the queue when this request finishes
555
- resultPromise.finally(() => {
556
- this.processRequestQueue();
557
- }).catch(() => { }); // catch to prevent unhandled rejection during finally chain? no, finally returns new promise
558
-
559
- if (this.send(message)) {
560
- this.requestTracker.updateLastRequestSentAt();
561
- return resultPromise;
562
- } else {
563
- this.requestTracker.rejectRequest(requestId, new Error('Failed to send request'));
564
- throw new Error('Failed to send request');
565
- }
566
- }
567
-
568
- private processRequestQueue() {
569
- if (this.queuedRequestItems.length === 0) return;
570
-
571
- // while we have capacity and items
572
- while (
573
- this.queuedRequestItems.length > 0 &&
574
- this.requestTracker.getPendingCount() < this.requestTracker.getMaxPendingRequests()
575
- ) {
576
- const item = this.queuedRequestItems.shift();
577
- if (item) {
578
- this.sendRequestInternal(item.action, item.payload, item.options)
579
- .then(item.resolve)
580
- .catch(item.reject);
581
- }
582
- }
583
- }
584
-
585
- send(payload: AutomationBridgeMessage): boolean {
586
- const primarySocket = this.connectionManager.getPrimarySocket();
587
- if (!primarySocket || primarySocket.readyState !== WebSocket.OPEN) {
588
- this.log.warn('Attempted to send automation message without an active primary connection');
589
- return false;
590
- }
591
- try {
592
- primarySocket.send(JSON.stringify(payload));
593
- return true;
594
- } catch (error) {
595
- this.log.error('Failed to send automation message', error);
596
- const errObj = error instanceof Error ? error : new Error(String(error));
597
- const primaryInfo = this.connectionManager.getActiveSockets().get(primarySocket);
598
- const errorWithPort = Object.assign(errObj, { port: primaryInfo?.port });
599
- this.emitAutomation('error', errorWithPort);
600
- return false;
601
- }
602
- }
603
-
604
- private broadcast(payload: AutomationBridgeMessage): boolean {
605
- const sockets = this.connectionManager.getActiveSockets();
606
- if (sockets.size === 0) {
607
- this.log.warn('Attempted to broadcast automation message without any active connections');
608
- return false;
609
- }
610
- let sentCount = 0;
611
- for (const [socket] of sockets) {
612
- if (socket.readyState === WebSocket.OPEN) {
613
- try {
614
- socket.send(JSON.stringify(payload));
615
- sentCount++;
616
- } catch (error) {
617
- this.log.error('Failed to broadcast automation message to socket', error);
618
- }
619
- }
620
- }
621
- return sentCount > 0;
622
- }
623
-
624
- private emitAutomation<K extends keyof AutomationBridgeEvents>(
625
- event: K,
626
- ...args: Parameters<AutomationBridgeEvents[K]>
627
- ): void {
628
- this.emit(event, ...args);
629
- }
630
- }