unreal-engine-mcp-server 0.4.7 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (438) hide show
  1. package/.env.example +26 -0
  2. package/.env.production +38 -7
  3. package/.eslintrc.json +0 -54
  4. package/.eslintrc.override.json +8 -0
  5. package/.github/ISSUE_TEMPLATE/bug_report.yml +94 -0
  6. package/.github/ISSUE_TEMPLATE/config.yml +8 -0
  7. package/.github/ISSUE_TEMPLATE/feature_request.yml +56 -0
  8. package/.github/copilot-instructions.md +478 -45
  9. package/.github/dependabot.yml +19 -0
  10. package/.github/labeler.yml +24 -0
  11. package/.github/labels.yml +70 -0
  12. package/.github/pull_request_template.md +42 -0
  13. package/.github/release-drafter.yml +148 -0
  14. package/.github/workflows/auto-merge.yml +38 -0
  15. package/.github/workflows/ci.yml +38 -0
  16. package/.github/workflows/dependency-review.yml +17 -0
  17. package/.github/workflows/gemini-issue-triage.yml +172 -0
  18. package/.github/workflows/greetings.yml +23 -0
  19. package/.github/workflows/labeler.yml +16 -0
  20. package/.github/workflows/links.yml +80 -0
  21. package/.github/workflows/pr-size-labeler.yml +137 -0
  22. package/.github/workflows/publish-mcp.yml +12 -7
  23. package/.github/workflows/release-drafter.yml +23 -0
  24. package/.github/workflows/release.yml +112 -0
  25. package/.github/workflows/semantic-pull-request.yml +35 -0
  26. package/.github/workflows/smoke-test.yml +36 -0
  27. package/.github/workflows/stale.yml +28 -0
  28. package/CHANGELOG.md +267 -31
  29. package/CONTRIBUTING.md +140 -0
  30. package/README.md +166 -71
  31. package/claude_desktop_config_example.json +7 -6
  32. package/dist/automation/bridge.d.ts +50 -0
  33. package/dist/automation/bridge.js +452 -0
  34. package/dist/automation/connection-manager.d.ts +23 -0
  35. package/dist/automation/connection-manager.js +107 -0
  36. package/dist/automation/handshake.d.ts +11 -0
  37. package/dist/automation/handshake.js +89 -0
  38. package/dist/automation/index.d.ts +3 -0
  39. package/dist/automation/index.js +3 -0
  40. package/dist/automation/message-handler.d.ts +12 -0
  41. package/dist/automation/message-handler.js +149 -0
  42. package/dist/automation/request-tracker.d.ts +25 -0
  43. package/dist/automation/request-tracker.js +98 -0
  44. package/dist/automation/types.d.ts +130 -0
  45. package/dist/automation/types.js +2 -0
  46. package/dist/cli.js +32 -5
  47. package/dist/config.d.ts +27 -0
  48. package/dist/config.js +60 -0
  49. package/dist/constants.d.ts +12 -0
  50. package/dist/constants.js +12 -0
  51. package/dist/graphql/resolvers.d.ts +268 -0
  52. package/dist/graphql/resolvers.js +743 -0
  53. package/dist/graphql/schema.d.ts +5 -0
  54. package/dist/graphql/schema.js +437 -0
  55. package/dist/graphql/server.d.ts +26 -0
  56. package/dist/graphql/server.js +115 -0
  57. package/dist/graphql/types.d.ts +7 -0
  58. package/dist/graphql/types.js +2 -0
  59. package/dist/handlers/resource-handlers.d.ts +20 -0
  60. package/dist/handlers/resource-handlers.js +180 -0
  61. package/dist/index.d.ts +31 -18
  62. package/dist/index.js +119 -619
  63. package/dist/prompts/index.js +4 -4
  64. package/dist/resources/actors.d.ts +17 -12
  65. package/dist/resources/actors.js +56 -76
  66. package/dist/resources/assets.d.ts +6 -14
  67. package/dist/resources/assets.js +115 -147
  68. package/dist/resources/levels.d.ts +13 -13
  69. package/dist/resources/levels.js +25 -34
  70. package/dist/server/resource-registry.d.ts +20 -0
  71. package/dist/server/resource-registry.js +37 -0
  72. package/dist/server/tool-registry.d.ts +23 -0
  73. package/dist/server/tool-registry.js +322 -0
  74. package/dist/server-setup.d.ts +21 -0
  75. package/dist/server-setup.js +111 -0
  76. package/dist/services/health-monitor.d.ts +34 -0
  77. package/dist/services/health-monitor.js +105 -0
  78. package/dist/services/metrics-server.d.ts +11 -0
  79. package/dist/services/metrics-server.js +105 -0
  80. package/dist/tools/actors.d.ts +147 -9
  81. package/dist/tools/actors.js +350 -311
  82. package/dist/tools/animation.d.ts +135 -4
  83. package/dist/tools/animation.js +510 -411
  84. package/dist/tools/assets.d.ts +117 -19
  85. package/dist/tools/assets.js +259 -284
  86. package/dist/tools/audio.d.ts +102 -42
  87. package/dist/tools/audio.js +272 -685
  88. package/dist/tools/base-tool.d.ts +17 -0
  89. package/dist/tools/base-tool.js +46 -0
  90. package/dist/tools/behavior-tree.d.ts +94 -0
  91. package/dist/tools/behavior-tree.js +39 -0
  92. package/dist/tools/blueprint/helpers.d.ts +29 -0
  93. package/dist/tools/blueprint/helpers.js +182 -0
  94. package/dist/tools/blueprint.d.ts +228 -118
  95. package/dist/tools/blueprint.js +685 -832
  96. package/dist/tools/consolidated-tool-definitions.d.ts +5462 -1781
  97. package/dist/tools/consolidated-tool-definitions.js +829 -496
  98. package/dist/tools/consolidated-tool-handlers.d.ts +2 -1
  99. package/dist/tools/consolidated-tool-handlers.js +211 -1026
  100. package/dist/tools/debug.d.ts +143 -85
  101. package/dist/tools/debug.js +234 -180
  102. package/dist/tools/dynamic-handler-registry.d.ts +11 -0
  103. package/dist/tools/dynamic-handler-registry.js +101 -0
  104. package/dist/tools/editor.d.ts +139 -18
  105. package/dist/tools/editor.js +239 -244
  106. package/dist/tools/engine.d.ts +10 -4
  107. package/dist/tools/engine.js +13 -5
  108. package/dist/tools/environment.d.ts +36 -0
  109. package/dist/tools/environment.js +267 -0
  110. package/dist/tools/foliage.d.ts +105 -14
  111. package/dist/tools/foliage.js +219 -331
  112. package/dist/tools/handlers/actor-handlers.d.ts +3 -0
  113. package/dist/tools/handlers/actor-handlers.js +232 -0
  114. package/dist/tools/handlers/animation-handlers.d.ts +3 -0
  115. package/dist/tools/handlers/animation-handlers.js +185 -0
  116. package/dist/tools/handlers/argument-helper.d.ts +16 -0
  117. package/dist/tools/handlers/argument-helper.js +80 -0
  118. package/dist/tools/handlers/asset-handlers.d.ts +3 -0
  119. package/dist/tools/handlers/asset-handlers.js +496 -0
  120. package/dist/tools/handlers/audio-handlers.d.ts +3 -0
  121. package/dist/tools/handlers/audio-handlers.js +166 -0
  122. package/dist/tools/handlers/blueprint-handlers.d.ts +4 -0
  123. package/dist/tools/handlers/blueprint-handlers.js +358 -0
  124. package/dist/tools/handlers/common-handlers.d.ts +14 -0
  125. package/dist/tools/handlers/common-handlers.js +56 -0
  126. package/dist/tools/handlers/editor-handlers.d.ts +3 -0
  127. package/dist/tools/handlers/editor-handlers.js +119 -0
  128. package/dist/tools/handlers/effect-handlers.d.ts +3 -0
  129. package/dist/tools/handlers/effect-handlers.js +171 -0
  130. package/dist/tools/handlers/environment-handlers.d.ts +3 -0
  131. package/dist/tools/handlers/environment-handlers.js +170 -0
  132. package/dist/tools/handlers/graph-handlers.d.ts +3 -0
  133. package/dist/tools/handlers/graph-handlers.js +90 -0
  134. package/dist/tools/handlers/input-handlers.d.ts +3 -0
  135. package/dist/tools/handlers/input-handlers.js +21 -0
  136. package/dist/tools/handlers/inspect-handlers.d.ts +3 -0
  137. package/dist/tools/handlers/inspect-handlers.js +383 -0
  138. package/dist/tools/handlers/level-handlers.d.ts +3 -0
  139. package/dist/tools/handlers/level-handlers.js +237 -0
  140. package/dist/tools/handlers/lighting-handlers.d.ts +3 -0
  141. package/dist/tools/handlers/lighting-handlers.js +144 -0
  142. package/dist/tools/handlers/performance-handlers.d.ts +3 -0
  143. package/dist/tools/handlers/performance-handlers.js +130 -0
  144. package/dist/tools/handlers/pipeline-handlers.d.ts +3 -0
  145. package/dist/tools/handlers/pipeline-handlers.js +110 -0
  146. package/dist/tools/handlers/sequence-handlers.d.ts +3 -0
  147. package/dist/tools/handlers/sequence-handlers.js +376 -0
  148. package/dist/tools/handlers/system-handlers.d.ts +4 -0
  149. package/dist/tools/handlers/system-handlers.js +506 -0
  150. package/dist/tools/input.d.ts +19 -0
  151. package/dist/tools/input.js +89 -0
  152. package/dist/tools/introspection.d.ts +103 -40
  153. package/dist/tools/introspection.js +425 -568
  154. package/dist/tools/landscape.d.ts +97 -36
  155. package/dist/tools/landscape.js +280 -409
  156. package/dist/tools/level.d.ts +130 -10
  157. package/dist/tools/level.js +639 -675
  158. package/dist/tools/lighting.d.ts +77 -38
  159. package/dist/tools/lighting.js +441 -943
  160. package/dist/tools/logs.d.ts +3 -3
  161. package/dist/tools/logs.js +5 -57
  162. package/dist/tools/materials.d.ts +91 -24
  163. package/dist/tools/materials.js +190 -118
  164. package/dist/tools/niagara.d.ts +149 -39
  165. package/dist/tools/niagara.js +232 -182
  166. package/dist/tools/performance.d.ts +27 -12
  167. package/dist/tools/performance.js +204 -122
  168. package/dist/tools/physics.d.ts +32 -77
  169. package/dist/tools/physics.js +171 -582
  170. package/dist/tools/property-dictionary.d.ts +13 -0
  171. package/dist/tools/property-dictionary.js +82 -0
  172. package/dist/tools/sequence.d.ts +73 -48
  173. package/dist/tools/sequence.js +196 -748
  174. package/dist/tools/tool-definition-utils.d.ts +59 -0
  175. package/dist/tools/tool-definition-utils.js +35 -0
  176. package/dist/tools/ui.d.ts +66 -34
  177. package/dist/tools/ui.js +134 -214
  178. package/dist/types/env.d.ts +0 -3
  179. package/dist/types/env.js +0 -7
  180. package/dist/types/tool-interfaces.d.ts +898 -0
  181. package/dist/types/tool-interfaces.js +2 -0
  182. package/dist/types/tool-types.d.ts +183 -19
  183. package/dist/types/tool-types.js +0 -4
  184. package/dist/unreal-bridge.d.ts +24 -131
  185. package/dist/unreal-bridge.js +364 -1506
  186. package/dist/utils/command-validator.d.ts +9 -0
  187. package/dist/utils/command-validator.js +67 -0
  188. package/dist/utils/elicitation.d.ts +1 -1
  189. package/dist/utils/elicitation.js +12 -15
  190. package/dist/utils/error-handler.d.ts +2 -51
  191. package/dist/utils/error-handler.js +11 -87
  192. package/dist/utils/ini-reader.d.ts +3 -0
  193. package/dist/utils/ini-reader.js +69 -0
  194. package/dist/utils/logger.js +9 -6
  195. package/dist/utils/normalize.d.ts +3 -0
  196. package/dist/utils/normalize.js +56 -0
  197. package/dist/utils/response-factory.d.ts +7 -0
  198. package/dist/utils/response-factory.js +33 -0
  199. package/dist/utils/response-validator.d.ts +3 -24
  200. package/dist/utils/response-validator.js +130 -81
  201. package/dist/utils/result-helpers.d.ts +4 -5
  202. package/dist/utils/result-helpers.js +15 -16
  203. package/dist/utils/safe-json.js +5 -11
  204. package/dist/utils/unreal-command-queue.d.ts +24 -0
  205. package/dist/utils/unreal-command-queue.js +120 -0
  206. package/dist/utils/validation.d.ts +0 -40
  207. package/dist/utils/validation.js +1 -78
  208. package/dist/wasm/index.d.ts +70 -0
  209. package/dist/wasm/index.js +535 -0
  210. package/docs/GraphQL-API.md +888 -0
  211. package/docs/Migration-Guide-v0.5.0.md +692 -0
  212. package/docs/Roadmap.md +53 -0
  213. package/docs/WebAssembly-Integration.md +628 -0
  214. package/docs/editor-plugin-extension.md +370 -0
  215. package/docs/handler-mapping.md +242 -0
  216. package/docs/native-automation-progress.md +128 -0
  217. package/docs/testing-guide.md +423 -0
  218. package/mcp-config-example.json +6 -6
  219. package/package.json +60 -27
  220. package/plugins/McpAutomationBridge/Config/FilterPlugin.ini +8 -0
  221. package/plugins/McpAutomationBridge/McpAutomationBridge.uplugin +64 -0
  222. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/McpAutomationBridge.Build.cs +189 -0
  223. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.cpp +22 -0
  224. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.h +30 -0
  225. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeHelpers.h +1983 -0
  226. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeModule.cpp +72 -0
  227. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSettings.cpp +46 -0
  228. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSubsystem.cpp +581 -0
  229. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AnimationHandlers.cpp +2394 -0
  230. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetQueryHandlers.cpp +300 -0
  231. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetWorkflowHandlers.cpp +2807 -0
  232. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AudioHandlers.cpp +1087 -0
  233. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BehaviorTreeHandlers.cpp +488 -0
  234. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.cpp +643 -0
  235. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.h +31 -0
  236. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintGraphHandlers.cpp +1184 -0
  237. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers.cpp +5652 -0
  238. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers_List.cpp +152 -0
  239. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ControlHandlers.cpp +2614 -0
  240. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_DebugHandlers.cpp +42 -0
  241. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EditorFunctionHandlers.cpp +1237 -0
  242. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EffectHandlers.cpp +1701 -0
  243. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EnvironmentHandlers.cpp +2145 -0
  244. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_FoliageHandlers.cpp +954 -0
  245. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InputHandlers.cpp +209 -0
  246. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InsightsHandlers.cpp +41 -0
  247. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LandscapeHandlers.cpp +1164 -0
  248. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LevelHandlers.cpp +762 -0
  249. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LightingHandlers.cpp +634 -0
  250. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LogHandlers.cpp +136 -0
  251. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_MaterialGraphHandlers.cpp +494 -0
  252. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraGraphHandlers.cpp +278 -0
  253. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraHandlers.cpp +625 -0
  254. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PerformanceHandlers.cpp +401 -0
  255. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PipelineHandlers.cpp +67 -0
  256. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ProcessRequest.cpp +735 -0
  257. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PropertyHandlers.cpp +2634 -0
  258. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_RenderHandlers.cpp +189 -0
  259. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.cpp +917 -0
  260. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.h +39 -0
  261. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequenceHandlers.cpp +2670 -0
  262. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequencerHandlers.cpp +519 -0
  263. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_TestHandlers.cpp +38 -0
  264. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_UiHandlers.cpp +668 -0
  265. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_WorldPartitionHandlers.cpp +346 -0
  266. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.cpp +1330 -0
  267. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.h +149 -0
  268. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpConnectionManager.cpp +783 -0
  269. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSettings.h +115 -0
  270. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSubsystem.h +796 -0
  271. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpConnectionManager.h +117 -0
  272. package/scripts/check-unreal-connection.mjs +19 -0
  273. package/scripts/clean-tmp.js +23 -0
  274. package/scripts/patch-wasm.js +26 -0
  275. package/scripts/run-all-tests.mjs +131 -0
  276. package/scripts/smoke-test.ts +94 -0
  277. package/scripts/sync-mcp-plugin.js +143 -0
  278. package/scripts/test-no-plugin-alternates.mjs +113 -0
  279. package/scripts/validate-server.js +46 -0
  280. package/scripts/verify-automation-bridge.js +200 -0
  281. package/server.json +57 -21
  282. package/src/automation/bridge.ts +558 -0
  283. package/src/automation/connection-manager.ts +130 -0
  284. package/src/automation/handshake.ts +99 -0
  285. package/src/automation/index.ts +2 -0
  286. package/src/automation/message-handler.ts +167 -0
  287. package/src/automation/request-tracker.ts +123 -0
  288. package/src/automation/types.ts +107 -0
  289. package/src/cli.ts +33 -6
  290. package/src/config.ts +73 -0
  291. package/src/constants.ts +12 -0
  292. package/src/graphql/resolvers.ts +1010 -0
  293. package/src/graphql/schema.ts +452 -0
  294. package/src/graphql/server.ts +154 -0
  295. package/src/graphql/types.ts +7 -0
  296. package/src/handlers/resource-handlers.ts +186 -0
  297. package/src/index.ts +152 -663
  298. package/src/prompts/index.ts +4 -4
  299. package/src/resources/actors.ts +58 -76
  300. package/src/resources/assets.ts +147 -134
  301. package/src/resources/levels.ts +28 -33
  302. package/src/server/resource-registry.ts +47 -0
  303. package/src/server/tool-registry.ts +354 -0
  304. package/src/server-setup.ts +148 -0
  305. package/src/services/health-monitor.ts +132 -0
  306. package/src/services/metrics-server.ts +142 -0
  307. package/src/tools/actors.ts +417 -322
  308. package/src/tools/animation.ts +671 -461
  309. package/src/tools/assets.ts +353 -289
  310. package/src/tools/audio.ts +323 -766
  311. package/src/tools/base-tool.ts +52 -0
  312. package/src/tools/behavior-tree.ts +45 -0
  313. package/src/tools/blueprint/helpers.ts +189 -0
  314. package/src/tools/blueprint.ts +787 -965
  315. package/src/tools/consolidated-tool-definitions.ts +993 -515
  316. package/src/tools/consolidated-tool-handlers.ts +272 -1139
  317. package/src/tools/debug.ts +292 -187
  318. package/src/tools/dynamic-handler-registry.ts +151 -0
  319. package/src/tools/editor.ts +309 -246
  320. package/src/tools/engine.ts +14 -3
  321. package/src/tools/environment.ts +287 -0
  322. package/src/tools/foliage.ts +314 -379
  323. package/src/tools/handlers/actor-handlers.ts +271 -0
  324. package/src/tools/handlers/animation-handlers.ts +237 -0
  325. package/src/tools/handlers/argument-helper.ts +142 -0
  326. package/src/tools/handlers/asset-handlers.ts +532 -0
  327. package/src/tools/handlers/audio-handlers.ts +194 -0
  328. package/src/tools/handlers/blueprint-handlers.ts +380 -0
  329. package/src/tools/handlers/common-handlers.ts +87 -0
  330. package/src/tools/handlers/editor-handlers.ts +123 -0
  331. package/src/tools/handlers/effect-handlers.ts +220 -0
  332. package/src/tools/handlers/environment-handlers.ts +183 -0
  333. package/src/tools/handlers/graph-handlers.ts +116 -0
  334. package/src/tools/handlers/input-handlers.ts +28 -0
  335. package/src/tools/handlers/inspect-handlers.ts +450 -0
  336. package/src/tools/handlers/level-handlers.ts +252 -0
  337. package/src/tools/handlers/lighting-handlers.ts +147 -0
  338. package/src/tools/handlers/performance-handlers.ts +132 -0
  339. package/src/tools/handlers/pipeline-handlers.ts +127 -0
  340. package/src/tools/handlers/sequence-handlers.ts +415 -0
  341. package/src/tools/handlers/system-handlers.ts +564 -0
  342. package/src/tools/input.ts +101 -0
  343. package/src/tools/introspection.ts +493 -584
  344. package/src/tools/landscape.ts +394 -489
  345. package/src/tools/level.ts +752 -694
  346. package/src/tools/lighting.ts +583 -984
  347. package/src/tools/logs.ts +9 -57
  348. package/src/tools/materials.ts +231 -121
  349. package/src/tools/niagara.ts +293 -168
  350. package/src/tools/performance.ts +320 -168
  351. package/src/tools/physics.ts +268 -613
  352. package/src/tools/property-dictionary.ts +98 -0
  353. package/src/tools/sequence.ts +255 -815
  354. package/src/tools/tool-definition-utils.ts +35 -0
  355. package/src/tools/ui.ts +207 -283
  356. package/src/types/env.ts +0 -10
  357. package/src/types/tool-interfaces.ts +250 -0
  358. package/src/types/tool-types.ts +243 -21
  359. package/src/unreal-bridge.ts +460 -1550
  360. package/src/utils/command-validator.ts +75 -0
  361. package/src/utils/elicitation.ts +10 -7
  362. package/src/utils/error-handler.ts +14 -90
  363. package/src/utils/ini-reader.ts +86 -0
  364. package/src/utils/logger.ts +8 -3
  365. package/src/utils/normalize.ts +60 -0
  366. package/src/utils/response-factory.ts +39 -0
  367. package/src/utils/response-validator.ts +176 -56
  368. package/src/utils/result-helpers.ts +21 -19
  369. package/src/utils/safe-json.ts +14 -11
  370. package/src/utils/unreal-command-queue.ts +152 -0
  371. package/src/utils/validation.ts +4 -1
  372. package/src/wasm/index.ts +838 -0
  373. package/test-server.mjs +100 -0
  374. package/tests/run-unreal-tool-tests.mjs +242 -14
  375. package/tests/test-animation.mjs +44 -0
  376. package/tests/test-asset-advanced.mjs +82 -0
  377. package/tests/test-asset-errors.mjs +35 -0
  378. package/tests/test-audio.mjs +219 -0
  379. package/tests/test-automation-timeouts.mjs +98 -0
  380. package/tests/test-behavior-tree.mjs +261 -0
  381. package/tests/test-blueprint-events.mjs +35 -0
  382. package/tests/test-blueprint-graph.mjs +79 -0
  383. package/tests/test-blueprint.mjs +577 -0
  384. package/tests/test-client-mode.mjs +86 -0
  385. package/tests/test-console-command.mjs +56 -0
  386. package/tests/test-control-actor.mjs +425 -0
  387. package/tests/test-control-editor.mjs +80 -0
  388. package/tests/test-extra-tools.mjs +38 -0
  389. package/tests/test-graphql.mjs +322 -0
  390. package/tests/test-inspect.mjs +72 -0
  391. package/tests/test-landscape.mjs +60 -0
  392. package/tests/test-manage-asset.mjs +438 -0
  393. package/tests/test-manage-level.mjs +70 -0
  394. package/tests/test-materials.mjs +356 -0
  395. package/tests/test-niagara.mjs +185 -0
  396. package/tests/test-no-inline-python.mjs +122 -0
  397. package/tests/test-plugin-handshake.mjs +82 -0
  398. package/tests/test-render.mjs +33 -0
  399. package/tests/test-runner.mjs +933 -0
  400. package/tests/test-search-assets.mjs +66 -0
  401. package/tests/test-sequence.mjs +68 -0
  402. package/tests/test-system.mjs +57 -0
  403. package/tests/test-wasm.mjs +193 -0
  404. package/tests/test-world-partition.mjs +215 -0
  405. package/tsconfig.json +3 -3
  406. package/wasm/Cargo.lock +363 -0
  407. package/wasm/Cargo.toml +42 -0
  408. package/wasm/LICENSE +21 -0
  409. package/wasm/README.md +253 -0
  410. package/wasm/src/dependency_resolver.rs +377 -0
  411. package/wasm/src/lib.rs +153 -0
  412. package/wasm/src/property_parser.rs +271 -0
  413. package/wasm/src/transform_math.rs +396 -0
  414. package/wasm/tests/integration.rs +109 -0
  415. package/.github/workflows/smithery-build.yml +0 -29
  416. package/dist/tools/build_environment_advanced.d.ts +0 -65
  417. package/dist/tools/build_environment_advanced.js +0 -633
  418. package/dist/tools/rc.d.ts +0 -110
  419. package/dist/tools/rc.js +0 -437
  420. package/dist/tools/visual.d.ts +0 -40
  421. package/dist/tools/visual.js +0 -282
  422. package/dist/utils/http.d.ts +0 -6
  423. package/dist/utils/http.js +0 -151
  424. package/dist/utils/python-output.d.ts +0 -18
  425. package/dist/utils/python-output.js +0 -290
  426. package/dist/utils/python.d.ts +0 -2
  427. package/dist/utils/python.js +0 -4
  428. package/dist/utils/stdio-redirect.d.ts +0 -2
  429. package/dist/utils/stdio-redirect.js +0 -20
  430. package/docs/unreal-tool-test-cases.md +0 -574
  431. package/smithery.yaml +0 -29
  432. package/src/tools/build_environment_advanced.ts +0 -732
  433. package/src/tools/rc.ts +0 -515
  434. package/src/tools/visual.ts +0 -281
  435. package/src/utils/http.ts +0 -187
  436. package/src/utils/python-output.ts +0 -351
  437. package/src/utils/python.ts +0 -3
  438. package/src/utils/stdio-redirect.ts +0 -18
@@ -0,0 +1,838 @@
1
+ /**
2
+ * WebAssembly Integration Module
3
+ *
4
+ * This module provides a high-level interface to WebAssembly-optimized
5
+ * operations for performance-critical tasks in the MCP server.
6
+ *
7
+ * Features:
8
+ * - Property parsing with fallback to TypeScript
9
+ * - Transform calculations (vector/matrix math)
10
+ * - Asset dependency resolution
11
+ * - Performance monitoring
12
+ */
13
+
14
+ import { Logger } from '../utils/logger.js';
15
+
16
+ // Dynamic import for WASM module
17
+ type WASMModule = any;
18
+
19
+ interface WASMConfig {
20
+ enabled?: boolean;
21
+ wasmPath?: string;
22
+ fallbackEnabled?: boolean;
23
+ performanceMonitoring?: boolean;
24
+ }
25
+
26
+ interface PerformanceMetrics {
27
+ operation: string;
28
+ duration: number;
29
+ timestamp: number;
30
+ useWASM: boolean;
31
+ }
32
+
33
+ const isNodeEnvironment =
34
+ typeof process !== 'undefined' &&
35
+ process.versions != null &&
36
+ process.versions.node != null;
37
+
38
+ let nodeFileFetchPatched = false;
39
+
40
+ async function ensureNodeFileFetchForWasm(): Promise<void> {
41
+ if (!isNodeEnvironment || nodeFileFetchPatched) {
42
+ return;
43
+ }
44
+
45
+ const originalFetch = (globalThis as any).fetch as
46
+ | (typeof fetch)
47
+ | undefined;
48
+
49
+ if (typeof originalFetch !== 'function') {
50
+ return;
51
+ }
52
+
53
+ try {
54
+ const fs = await import('node:fs/promises');
55
+ const url = await import('node:url');
56
+ const readFile = (fs as any).readFile as (path: string) => Promise<Buffer>;
57
+ const fileURLToPath = (url as any).fileURLToPath as (u: URL | string) => string;
58
+
59
+ const toUrl = (input: any): URL | null => {
60
+ try {
61
+ if (input instanceof URL) {
62
+ return input;
63
+ }
64
+ // Node fetch often receives a string URL
65
+ if (typeof input === 'string') {
66
+ return new URL(input);
67
+ }
68
+ // Handle Request objects if available
69
+ const RequestCtor = (globalThis as any).Request;
70
+ if (RequestCtor && input instanceof RequestCtor && typeof input.url === 'string') {
71
+ return new URL(input.url);
72
+ }
73
+ } catch {
74
+ // Ignore parse errors and fall through
75
+ }
76
+ return null;
77
+ };
78
+
79
+ (globalThis as any).fetch = (async (input: any, init?: any) => {
80
+ try {
81
+ const target = toUrl(input);
82
+ if (target && target.protocol === 'file:') {
83
+ const filePath = fileURLToPath(target);
84
+ const data = await readFile(filePath);
85
+
86
+ // Return a raw ArrayBuffer/Uint8Array so wasm-pack's loader can
87
+ // pass it directly to WebAssembly.instantiate as a buffer source.
88
+ const buffer = data.buffer.slice(
89
+ data.byteOffset,
90
+ data.byteOffset + data.byteLength
91
+ );
92
+
93
+ return buffer;
94
+ }
95
+ } catch {
96
+ // Fall through to original fetch if anything goes wrong
97
+ }
98
+
99
+ return (originalFetch as any)(input, init);
100
+ }) as typeof fetch;
101
+
102
+ nodeFileFetchPatched = true;
103
+ } catch {
104
+ // If the Node-specific modules are unavailable for some reason,
105
+ // leave fetch as-is and let the normal error handling occur.
106
+ }
107
+ }
108
+
109
+ export class WASMIntegration {
110
+ private log = new Logger('WASMIntegration');
111
+ private module: WASMModule | null = null;
112
+ private config: Required<WASMConfig>;
113
+ private metrics: PerformanceMetrics[] = [];
114
+ private maxMetrics = 1000;
115
+ private initialized = false;
116
+ // Track whether we've already determined that the optional WASM bundle is
117
+ // unavailable (for example, ERR_MODULE_NOT_FOUND). When set, future
118
+ // initialize() calls become no-ops and rely on TypeScript fallbacks.
119
+ private moduleUnavailable = false;
120
+
121
+ constructor(config: WASMConfig = {}) {
122
+ const envFlag = process.env.WASM_ENABLED;
123
+ const envEnabled = envFlag === undefined ? true : envFlag === 'true';
124
+
125
+ // Resolve a sensible default WASM bundle path that works both when this
126
+ // module is executed from compiled dist/ (Node runs dist/wasm/index.js)
127
+ // and when run directly from src/ (e.g. via ts-node). When running from
128
+ // dist/, the generated bundle lives under src/wasm/pkg by default, so we
129
+ // point back to the source tree. When running from src/, we expect the
130
+ // pkg/ directory to sit alongside index.ts.
131
+ const here = new URL('.', import.meta.url);
132
+ const herePath = here.pathname.replace(/\\/g, '/');
133
+ const defaultUrl = herePath.includes('/dist/')
134
+ ? new URL('../../src/wasm/pkg/unreal_mcp_wasm.js', import.meta.url)
135
+ : new URL('./pkg/unreal_mcp_wasm.js', import.meta.url);
136
+ const defaultWasmPath = defaultUrl.href;
137
+
138
+ this.config = {
139
+ enabled: config.enabled ?? envEnabled,
140
+ wasmPath: config.wasmPath ?? process.env.WASM_PATH ?? defaultWasmPath,
141
+ fallbackEnabled: config.fallbackEnabled ?? true,
142
+ performanceMonitoring: config.performanceMonitoring ?? true
143
+ };
144
+ }
145
+
146
+ /**
147
+ * Initialize the WebAssembly module
148
+ */
149
+ async initialize(): Promise<void> {
150
+ if (this.initialized && this.module) {
151
+ this.log.debug('WASM module already initialized');
152
+ return;
153
+ }
154
+
155
+ // If a prior initialization attempt determined that the module is not
156
+ // available (for example, ERR_MODULE_NOT_FOUND), do not keep trying to
157
+ // load it on every call. The TypeScript fallbacks will remain active.
158
+ if (this.moduleUnavailable) {
159
+ return;
160
+ }
161
+
162
+ if (!this.config.enabled) {
163
+ this.log.info('WASM integration is disabled');
164
+ return;
165
+ }
166
+
167
+ try {
168
+ this.log.info(`Loading WASM module from ${this.config.wasmPath}...`);
169
+
170
+ // When running under Node, wasm-pack's web target will attempt to
171
+ // fetch() the compiled .wasm via a file:// URL. Node's built-in
172
+ // fetch does not currently support file://, so we install a narrow
173
+ // polyfill that handles file URLs by reading from disk and delegates
174
+ // all other requests to the original fetch implementation.
175
+ await ensureNodeFileFetchForWasm();
176
+
177
+ // Dynamic import of the WASM module
178
+ const wasmModule = await import(this.config.wasmPath);
179
+ await wasmModule.default();
180
+
181
+ this.module = wasmModule;
182
+ this.initialized = true;
183
+
184
+ this.log.info('✅ WebAssembly module initialized successfully');
185
+
186
+ // Log available functions for debugging
187
+ this.log.debug('WASM module functions:', {
188
+ hasPropertyParser: typeof wasmModule.PropertyParser === 'function',
189
+ hasTransformCalculator: typeof wasmModule.TransformCalculator === 'function',
190
+ hasVector: typeof wasmModule.Vector === 'function',
191
+ hasUtils: typeof wasmModule.Utils === 'function'
192
+ });
193
+ } catch (error) {
194
+ this.log.error('Failed to initialize WebAssembly module:', error);
195
+
196
+ const code = (error as any)?.code;
197
+ if (code === 'ERR_MODULE_NOT_FOUND') {
198
+ // The WASM bundle is an optional optimization. When it has not been
199
+ // built, log a single concise warning and then rely on the
200
+ // TypeScript fallbacks for the rest of the process without
201
+ // repeatedly attempting to import the missing file.
202
+ this.log.warn('WebAssembly module not found. To enable WASM, run "npm run build:wasm". To silence this warning, set WASM_ENABLED=false.');
203
+ this.moduleUnavailable = true;
204
+ }
205
+
206
+ this.log.warn('Falling back to TypeScript implementations');
207
+
208
+ if (!this.config.fallbackEnabled) {
209
+ throw new Error('WASM initialization failed and fallbacks are disabled');
210
+ }
211
+
212
+ this.module = null;
213
+ this.initialized = false;
214
+ }
215
+ }
216
+
217
+ /**
218
+ * Check if WASM is initialized and ready
219
+ */
220
+ isReady(): boolean {
221
+ return this.initialized && this.module !== null;
222
+ }
223
+
224
+ /**
225
+ * Check if WebAssembly is supported in the environment
226
+ */
227
+ static isSupported(): boolean {
228
+ return typeof WebAssembly === 'object' &&
229
+ typeof WebAssembly.instantiate === 'function';
230
+ }
231
+
232
+ /**
233
+ * Parse properties with WASM optimization and TypeScript fallback
234
+ */
235
+ async parseProperties(jsonStr: string, options?: { maxDepth?: number }): Promise<any> {
236
+ const start = performance.now();
237
+
238
+ if (!this.isReady()) {
239
+ await this.initialize();
240
+ }
241
+
242
+ // Try WASM first if available
243
+ if (this.module && typeof this.module.PropertyParser === 'function') {
244
+ try {
245
+ const parser = new this.module.PropertyParser();
246
+ const result = parser.parse_properties(jsonStr, options?.maxDepth ?? 100);
247
+
248
+ const duration = performance.now() - start;
249
+ this.recordMetrics('parse_properties', duration, true);
250
+
251
+ return result;
252
+ } catch (error) {
253
+ this.log.warn('WASM property parsing failed, falling back to TypeScript:', error);
254
+ }
255
+ }
256
+
257
+ // Fallback to TypeScript
258
+ const duration = performance.now() - start;
259
+ this.recordMetrics('parse_properties', duration, false);
260
+
261
+ return this.fallbackParseProperties(jsonStr);
262
+ }
263
+
264
+ /**
265
+ * Compose transform (location, rotation, scale) with WASM optimization
266
+ */
267
+ composeTransform(
268
+ location: [number, number, number],
269
+ rotation: [number, number, number],
270
+ scale: [number, number, number]
271
+ ): Float32Array {
272
+ const start = performance.now();
273
+
274
+ if (this.isReady() && this.module && typeof this.module.TransformCalculator === 'function') {
275
+ try {
276
+ const calculator = new this.module.TransformCalculator();
277
+ const result = calculator.composeTransform(
278
+ new Float32Array(location),
279
+ new Float32Array(rotation),
280
+ new Float32Array(scale)
281
+ );
282
+
283
+ const duration = performance.now() - start;
284
+ this.recordMetrics('compose_transform', duration, true);
285
+
286
+ return new Float32Array(result);
287
+ } catch (error) {
288
+ this.log.warn('WASM transform calculation failed, falling back to TypeScript:', error);
289
+ }
290
+ }
291
+
292
+ // Fallback to TypeScript
293
+ const duration = performance.now() - start;
294
+ this.recordMetrics('compose_transform', duration, false);
295
+
296
+ return this.fallbackComposeTransform(location, rotation, scale);
297
+ }
298
+
299
+ /**
300
+ * Decompose a transformation matrix
301
+ */
302
+ decomposeMatrix(matrix: Float32Array): number[] {
303
+ const start = performance.now();
304
+
305
+ if (this.isReady() && this.module && typeof this.module.TransformCalculator === 'function') {
306
+ try {
307
+ const calculator = new this.module.TransformCalculator();
308
+ const result = calculator.decomposeMatrix(matrix);
309
+
310
+ const duration = performance.now() - start;
311
+ this.recordMetrics('decompose_matrix', duration, true);
312
+
313
+ return Array.from(result);
314
+ } catch (error) {
315
+ this.log.warn('WASM matrix decomposition failed, falling back to TypeScript:', error);
316
+ }
317
+ }
318
+
319
+ // Fallback to TypeScript
320
+ const duration = performance.now() - start;
321
+ this.recordMetrics('decompose_matrix', duration, false);
322
+
323
+ return this.fallbackDecomposeMatrix(matrix);
324
+ }
325
+
326
+ /**
327
+ * Calculate vector operations with WASM
328
+ */
329
+ vectorAdd(
330
+ v1: [number, number, number],
331
+ v2: [number, number, number]
332
+ ): [number, number, number] {
333
+ const start = performance.now();
334
+
335
+ if (this.isReady() && this.module && typeof this.module.Vector === 'function') {
336
+ try {
337
+ const vec1 = new this.module.Vector(v1[0], v1[1], v1[2]);
338
+ const vec2 = new this.module.Vector(v2[0], v2[1], v2[2]);
339
+ const result = vec1.add(vec2);
340
+
341
+ const duration = performance.now() - start;
342
+ this.recordMetrics('vector_add', duration, true);
343
+
344
+ return [result.x, result.y, result.z];
345
+ } catch (error) {
346
+ this.log.warn('WASM vector addition failed, falling back to TypeScript:', error);
347
+ }
348
+ }
349
+
350
+ // Fallback to TypeScript
351
+ const duration = performance.now() - start;
352
+ this.recordMetrics('vector_add', duration, false);
353
+
354
+ return this.fallbackVectorAdd(v1, v2);
355
+ }
356
+
357
+ /**
358
+ * Resolve asset dependencies with WASM optimization
359
+ */
360
+ async resolveDependencies(
361
+ assetPath: string,
362
+ dependencies: Record<string, string[]>,
363
+ options?: { maxDepth?: number }
364
+ ): Promise<any> {
365
+ const start = performance.now();
366
+
367
+ if (!this.isReady()) {
368
+ await this.initialize();
369
+ }
370
+
371
+ // Try WASM first if available
372
+ if (this.module && typeof this.module.DependencyResolver === 'function') {
373
+ try {
374
+ const resolver = new this.module.DependencyResolver();
375
+ const dependenciesJson = JSON.stringify(dependencies);
376
+ const result = resolver.analyzeDependencies(
377
+ assetPath,
378
+ dependenciesJson,
379
+ options?.maxDepth ?? 100
380
+ );
381
+
382
+ const duration = performance.now() - start;
383
+ this.recordMetrics('resolve_dependencies', duration, true);
384
+
385
+ return result;
386
+ } catch (error) {
387
+ this.log.warn('WASM dependency resolution failed, falling back to TypeScript:', error);
388
+ }
389
+ }
390
+
391
+ // Fallback to TypeScript
392
+ const duration = performance.now() - start;
393
+ this.recordMetrics('resolve_dependencies', duration, false);
394
+
395
+ return this.fallbackResolveDependencies(assetPath, dependencies, options);
396
+ }
397
+
398
+ async calculateDependencyDepth(
399
+ assetPath: string,
400
+ dependencies: Record<string, string[]>,
401
+ options?: { maxDepth?: number }
402
+ ): Promise<number> {
403
+ const start = performance.now();
404
+
405
+ if (!this.isReady()) {
406
+ await this.initialize();
407
+ }
408
+
409
+ if (this.module && typeof this.module.DependencyResolver === 'function') {
410
+ try {
411
+ const resolver = new this.module.DependencyResolver();
412
+ const dependenciesJson = JSON.stringify(dependencies);
413
+ const result = resolver.calculateDepth(
414
+ assetPath,
415
+ dependenciesJson,
416
+ options?.maxDepth ?? 100
417
+ );
418
+
419
+ const duration = performance.now() - start;
420
+ this.recordMetrics('calculate_dependency_depth', duration, true);
421
+
422
+ return result as number;
423
+ } catch (error) {
424
+ this.log.warn('WASM dependency depth calculation failed, falling back to TypeScript:', error);
425
+ }
426
+ }
427
+
428
+ const duration = performance.now() - start;
429
+ this.recordMetrics('calculate_dependency_depth', duration, false);
430
+
431
+ return this.fallbackCalculateDependencyDepth(assetPath, dependencies, options);
432
+ }
433
+
434
+ async findCircularDependencies(
435
+ dependencies: Record<string, string[]>,
436
+ options?: { maxDepth?: number }
437
+ ): Promise<string[][]> {
438
+ const start = performance.now();
439
+
440
+ if (!this.isReady()) {
441
+ await this.initialize();
442
+ }
443
+
444
+ if (this.module && typeof this.module.DependencyResolver === 'function') {
445
+ try {
446
+ const resolver = new this.module.DependencyResolver();
447
+ const dependenciesJson = JSON.stringify(dependencies);
448
+ const result = resolver.findCircularDependencies(
449
+ dependenciesJson,
450
+ options?.maxDepth ?? 100
451
+ );
452
+
453
+ const duration = performance.now() - start;
454
+ this.recordMetrics('find_circular_dependencies', duration, true);
455
+
456
+ return result as string[][];
457
+ } catch (error) {
458
+ this.log.warn('WASM circular dependency detection failed, falling back to TypeScript:', error);
459
+ }
460
+ }
461
+
462
+ const duration = performance.now() - start;
463
+ this.recordMetrics('find_circular_dependencies', duration, false);
464
+
465
+ return this.fallbackFindCircularDependencies(dependencies, options);
466
+ }
467
+
468
+ async topologicalSort(
469
+ dependencies: Record<string, string[]>
470
+ ): Promise<string[]> {
471
+ const start = performance.now();
472
+
473
+ if (!this.isReady()) {
474
+ await this.initialize();
475
+ }
476
+
477
+ if (this.module && typeof this.module.DependencyResolver === 'function') {
478
+ try {
479
+ const resolver = new this.module.DependencyResolver();
480
+ const dependenciesJson = JSON.stringify(dependencies);
481
+ const result = resolver.topologicalSort(dependenciesJson);
482
+
483
+ const duration = performance.now() - start;
484
+ this.recordMetrics('topological_sort', duration, true);
485
+
486
+ return result as string[];
487
+ } catch (error) {
488
+ this.log.warn('WASM topological sort failed, falling back to TypeScript:', error);
489
+ }
490
+ }
491
+
492
+ const duration = performance.now() - start;
493
+ this.recordMetrics('topological_sort', duration, false);
494
+
495
+ return this.fallbackTopologicalSort(dependencies);
496
+ }
497
+
498
+ /**
499
+ * Get performance metrics for WASM operations
500
+ */
501
+ getMetrics(): {
502
+ totalOperations: number;
503
+ wasmOperations: number;
504
+ tsOperations: number;
505
+ averageTime: number;
506
+ operations: PerformanceMetrics[];
507
+ } {
508
+ const operations = this.metrics.slice(-this.maxMetrics);
509
+ const wasmOperations = operations.filter(m => m.useWASM).length;
510
+ const tsOperations = operations.filter(m => !m.useWASM).length;
511
+ const totalTime = operations.reduce((sum, m) => sum + m.duration, 0);
512
+ const averageTime = operations.length > 0 ? totalTime / operations.length : 0;
513
+
514
+ return {
515
+ totalOperations: operations.length,
516
+ wasmOperations,
517
+ tsOperations,
518
+ averageTime,
519
+ operations
520
+ };
521
+ }
522
+
523
+ /**
524
+ * Lightweight status information for observability/metrics.
525
+ */
526
+ getStatus(): {
527
+ enabled: boolean;
528
+ ready: boolean;
529
+ moduleUnavailable: boolean;
530
+ } {
531
+ return {
532
+ enabled: this.config.enabled,
533
+ ready: this.isReady(),
534
+ moduleUnavailable: this.moduleUnavailable
535
+ };
536
+ }
537
+
538
+ /**
539
+ * Clear performance metrics
540
+ */
541
+ clearMetrics(): void {
542
+ this.metrics = [];
543
+ }
544
+
545
+ /**
546
+ * Report performance summary
547
+ */
548
+ reportPerformance(): string {
549
+ const metrics = this.getMetrics();
550
+ const wasmPercentage = metrics.totalOperations > 0
551
+ ? ((metrics.wasmOperations / metrics.totalOperations) * 100).toFixed(1)
552
+ : '0';
553
+
554
+ const report = [
555
+ '=== WASM Performance Report ===',
556
+ `Total Operations: ${metrics.totalOperations}`,
557
+ `WASM Operations: ${metrics.wasmOperations} (${wasmPercentage}%)`,
558
+ `TypeScript Operations: ${metrics.tsOperations}`,
559
+ `Average Time: ${metrics.averageTime.toFixed(2)}ms`,
560
+ '=============================='
561
+ ].join('\n');
562
+
563
+ return report;
564
+ }
565
+
566
+ private recordMetrics(operation: string, duration: number, useWASM: boolean): void {
567
+ if (!this.config.performanceMonitoring) {
568
+ return;
569
+ }
570
+
571
+ this.metrics.push({
572
+ operation,
573
+ duration,
574
+ timestamp: Date.now(),
575
+ useWASM
576
+ });
577
+
578
+ // Keep only the last maxMetrics entries
579
+ if (this.metrics.length > this.maxMetrics) {
580
+ this.metrics.shift();
581
+ }
582
+ }
583
+
584
+ // TypeScript fallback implementations
585
+
586
+ private fallbackParseProperties(jsonStr: string): any {
587
+ try {
588
+ return JSON.parse(jsonStr);
589
+ } catch (error) {
590
+ this.log.error('Failed to parse JSON:', error);
591
+ throw error;
592
+ }
593
+ }
594
+
595
+ private fallbackComposeTransform(
596
+ location: [number, number, number],
597
+ rotation: [number, number, number],
598
+ scale: [number, number, number]
599
+ ): Float32Array {
600
+ // Simplified transformation matrix composition
601
+ const matrix = new Float32Array(16);
602
+
603
+ const [x, y, z] = location;
604
+ const [_pitch, _yaw, _roll] = rotation.map(angle => angle * Math.PI / 180);
605
+ const [sx, sy, sz] = scale;
606
+
607
+ // Create transformation matrix (simplified)
608
+ matrix[0] = sx;
609
+ matrix[5] = sy;
610
+ matrix[10] = sz;
611
+ matrix[12] = x;
612
+ matrix[13] = y;
613
+ matrix[14] = z;
614
+ matrix[15] = 1;
615
+
616
+ return matrix;
617
+ }
618
+
619
+ private fallbackDecomposeMatrix(matrix: Float32Array): number[] {
620
+ const location = [matrix[12], matrix[13], matrix[14]];
621
+ const scale = [
622
+ Math.sqrt(matrix[0] * matrix[0] + matrix[1] * matrix[1] + matrix[2] * matrix[2]),
623
+ Math.sqrt(matrix[4] * matrix[4] + matrix[5] * matrix[5] + matrix[6] * matrix[6]),
624
+ Math.sqrt(matrix[8] * matrix[8] + matrix[9] * matrix[9] + matrix[10] * matrix[10])
625
+ ];
626
+
627
+ const rotation = [0, 0, 0]; // Simplified
628
+
629
+ return [...location, ...rotation, ...scale];
630
+ }
631
+
632
+ private fallbackVectorAdd(
633
+ v1: [number, number, number],
634
+ v2: [number, number, number]
635
+ ): [number, number, number] {
636
+ return [
637
+ v1[0] + v2[0],
638
+ v1[1] + v2[1],
639
+ v1[2] + v2[2]
640
+ ];
641
+ }
642
+
643
+ private fallbackResolveDependencies(
644
+ assetPath: string,
645
+ dependencies: Record<string, string[]>,
646
+ options?: { maxDepth?: number }
647
+ ): any {
648
+ const maxDepth = options?.maxDepth ?? 100;
649
+ const visited = new Set<string>();
650
+ const result: any[] = [];
651
+ const queue: Array<{ path: string; depth: number }> = [
652
+ { path: assetPath, depth: 0 }
653
+ ];
654
+
655
+ while (queue.length > 0) {
656
+ const item = queue.shift();
657
+ if (!item) continue;
658
+
659
+ const { path, depth } = item;
660
+
661
+ if (depth > maxDepth || visited.has(path)) {
662
+ continue;
663
+ }
664
+
665
+ visited.add(path);
666
+
667
+ if (dependencies[path]) {
668
+ result.push({
669
+ path,
670
+ dependencies: dependencies[path],
671
+ depth
672
+ });
673
+
674
+ for (const dep of dependencies[path]) {
675
+ queue.push({ path: dep, depth: depth + 1 });
676
+ }
677
+ }
678
+ }
679
+
680
+ const totalCount = result.length;
681
+
682
+ return {
683
+ asset: assetPath,
684
+ dependencies: result,
685
+ total_dependency_count: totalCount,
686
+ max_depth: maxDepth,
687
+ analysis_time_ms: 0,
688
+ totalDependencyCount: totalCount,
689
+ maxDepth,
690
+ analysisTimeMs: 0,
691
+ circular_dependencies: [],
692
+ circularDependencies: []
693
+ };
694
+ }
695
+
696
+ private fallbackCalculateDependencyDepth(
697
+ assetPath: string,
698
+ dependencies: Record<string, string[]>,
699
+ options?: { maxDepth?: number }
700
+ ): number {
701
+ const maxDepth = options?.maxDepth ?? 100;
702
+ const visited = new Set<string>();
703
+
704
+ const dfs = (path: string, depthRemaining: number): number => {
705
+ if (visited.has(path) || depthRemaining === 0) {
706
+ return 0;
707
+ }
708
+
709
+ visited.add(path);
710
+ const deps = dependencies[path] || [];
711
+ if (!deps.length) {
712
+ visited.delete(path);
713
+ return 0;
714
+ }
715
+
716
+ let maxChildDepth = 0;
717
+ for (const dep of deps) {
718
+ const childDepth = dfs(dep, depthRemaining - 1);
719
+ if (childDepth > maxChildDepth) {
720
+ maxChildDepth = childDepth;
721
+ }
722
+ }
723
+
724
+ visited.delete(path);
725
+ return maxChildDepth + 1;
726
+ };
727
+
728
+ return dfs(assetPath, maxDepth);
729
+ }
730
+
731
+ private fallbackFindCircularDependencies(
732
+ dependencies: Record<string, string[]>,
733
+ options?: { maxDepth?: number }
734
+ ): string[][] {
735
+ const maxDepth = options?.maxDepth ?? 100;
736
+ const cycles: string[][] = [];
737
+ const visited = new Set<string>();
738
+ const stack = new Set<string>();
739
+
740
+ const dfs = (current: string, depth: number, path: string[]): void => {
741
+ if (depth > maxDepth) {
742
+ return;
743
+ }
744
+
745
+ visited.add(current);
746
+ stack.add(current);
747
+ path.push(current);
748
+
749
+ const deps = dependencies[current] || [];
750
+ for (const dep of deps) {
751
+ if (!visited.has(dep)) {
752
+ dfs(dep, depth + 1, path);
753
+ } else if (stack.has(dep)) {
754
+ const startIndex = path.indexOf(dep);
755
+ if (startIndex !== -1) {
756
+ cycles.push(path.slice(startIndex));
757
+ }
758
+ }
759
+ }
760
+
761
+ stack.delete(current);
762
+ path.pop();
763
+ };
764
+
765
+ for (const asset of Object.keys(dependencies)) {
766
+ if (!visited.has(asset)) {
767
+ dfs(asset, 0, []);
768
+ }
769
+ }
770
+
771
+ return cycles;
772
+ }
773
+
774
+ private fallbackTopologicalSort(
775
+ dependencies: Record<string, string[]>
776
+ ): string[] {
777
+ const inDegree = new Map<string, number>();
778
+ const graph = new Map<string, string[]>();
779
+
780
+ for (const [asset, deps] of Object.entries(dependencies)) {
781
+ if (!inDegree.has(asset)) {
782
+ inDegree.set(asset, 0);
783
+ }
784
+ for (const dep of deps) {
785
+ if (!inDegree.has(dep)) {
786
+ inDegree.set(dep, 0);
787
+ }
788
+ const list = graph.get(dep) || [];
789
+ list.push(asset);
790
+ graph.set(dep, list);
791
+ }
792
+ }
793
+
794
+ const queue: string[] = [];
795
+ for (const [asset, degree] of inDegree.entries()) {
796
+ if (degree === 0) {
797
+ queue.push(asset);
798
+ }
799
+ }
800
+
801
+ const sorted: string[] = [];
802
+
803
+ while (queue.length > 0) {
804
+ const asset = queue.shift() as string;
805
+ sorted.push(asset);
806
+
807
+ const dependents = graph.get(asset) || [];
808
+ for (const dependent of dependents) {
809
+ const current = inDegree.get(dependent) ?? 0;
810
+ const next = current - 1;
811
+ inDegree.set(dependent, next);
812
+ if (next === 0) {
813
+ queue.push(dependent);
814
+ }
815
+ }
816
+ }
817
+
818
+ return sorted;
819
+ }
820
+ }
821
+
822
+ // Create a singleton instance
823
+ export const wasmIntegration = new WASMIntegration();
824
+
825
+ // Export initialization function
826
+ export async function initializeWASM(config?: WASMConfig): Promise<void> {
827
+ const integration = config ? new WASMIntegration(config) : wasmIntegration;
828
+ await integration.initialize();
829
+ }
830
+
831
+ // Export utility functions
832
+ export function isWASMReady(): boolean {
833
+ return wasmIntegration.isReady();
834
+ }
835
+
836
+ export function getWASMPerformanceReport(): string {
837
+ return wasmIntegration.reportPerformance();
838
+ }