unreal-engine-mcp-server 0.5.0 → 0.5.2

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 (188) hide show
  1. package/.env.example +1 -1
  2. package/.github/release-drafter-config.yml +51 -0
  3. package/.github/workflows/greetings.yml +5 -1
  4. package/.github/workflows/labeler.yml +2 -1
  5. package/.github/workflows/publish-mcp.yml +2 -4
  6. package/.github/workflows/release-drafter.yml +3 -2
  7. package/.github/workflows/release.yml +3 -3
  8. package/CHANGELOG.md +109 -0
  9. package/CONTRIBUTING.md +1 -1
  10. package/GEMINI.md +115 -0
  11. package/Public/Plugin_setup_guide.mp4 +0 -0
  12. package/README.md +166 -200
  13. package/dist/automation/bridge.d.ts +1 -2
  14. package/dist/automation/bridge.js +24 -23
  15. package/dist/automation/connection-manager.d.ts +1 -0
  16. package/dist/automation/connection-manager.js +10 -0
  17. package/dist/automation/message-handler.js +5 -4
  18. package/dist/automation/request-tracker.d.ts +4 -0
  19. package/dist/automation/request-tracker.js +11 -3
  20. package/dist/config.d.ts +0 -1
  21. package/dist/config.js +0 -1
  22. package/dist/constants.d.ts +4 -0
  23. package/dist/constants.js +4 -0
  24. package/dist/graphql/loaders.d.ts +64 -0
  25. package/dist/graphql/loaders.js +117 -0
  26. package/dist/graphql/resolvers.d.ts +3 -3
  27. package/dist/graphql/resolvers.js +33 -30
  28. package/dist/graphql/server.js +3 -1
  29. package/dist/graphql/types.d.ts +2 -0
  30. package/dist/index.d.ts +2 -0
  31. package/dist/index.js +13 -2
  32. package/dist/server-setup.d.ts +0 -1
  33. package/dist/server-setup.js +0 -40
  34. package/dist/tools/actors.d.ts +58 -24
  35. package/dist/tools/actors.js +22 -6
  36. package/dist/tools/assets.d.ts +19 -71
  37. package/dist/tools/assets.js +28 -22
  38. package/dist/tools/base-tool.d.ts +4 -4
  39. package/dist/tools/base-tool.js +1 -1
  40. package/dist/tools/blueprint.d.ts +45 -61
  41. package/dist/tools/blueprint.js +43 -14
  42. package/dist/tools/consolidated-tool-definitions.js +2 -1
  43. package/dist/tools/consolidated-tool-handlers.js +96 -110
  44. package/dist/tools/dynamic-handler-registry.d.ts +11 -9
  45. package/dist/tools/dynamic-handler-registry.js +17 -95
  46. package/dist/tools/editor.d.ts +19 -193
  47. package/dist/tools/editor.js +11 -2
  48. package/dist/tools/environment.d.ts +8 -14
  49. package/dist/tools/foliage.d.ts +18 -143
  50. package/dist/tools/foliage.js +4 -2
  51. package/dist/tools/handlers/actor-handlers.d.ts +1 -1
  52. package/dist/tools/handlers/actor-handlers.js +14 -13
  53. package/dist/tools/handlers/asset-handlers.js +454 -454
  54. package/dist/tools/handlers/sequence-handlers.d.ts +1 -1
  55. package/dist/tools/handlers/sequence-handlers.js +24 -13
  56. package/dist/tools/introspection.d.ts +1 -1
  57. package/dist/tools/introspection.js +1 -1
  58. package/dist/tools/landscape.d.ts +16 -116
  59. package/dist/tools/landscape.js +7 -3
  60. package/dist/tools/level.d.ts +22 -103
  61. package/dist/tools/level.js +26 -18
  62. package/dist/tools/lighting.d.ts +54 -7
  63. package/dist/tools/lighting.js +9 -5
  64. package/dist/tools/materials.d.ts +1 -1
  65. package/dist/tools/materials.js +5 -1
  66. package/dist/tools/niagara.js +37 -2
  67. package/dist/tools/performance.d.ts +0 -1
  68. package/dist/tools/performance.js +0 -1
  69. package/dist/tools/physics.js +5 -1
  70. package/dist/tools/sequence.d.ts +24 -24
  71. package/dist/tools/sequence.js +13 -0
  72. package/dist/tools/ui.d.ts +0 -2
  73. package/dist/types/automation-responses.d.ts +115 -0
  74. package/dist/types/automation-responses.js +2 -0
  75. package/dist/types/responses.d.ts +249 -0
  76. package/dist/types/responses.js +2 -0
  77. package/dist/types/tool-interfaces.d.ts +135 -135
  78. package/dist/types/tool-types.d.ts +2 -0
  79. package/dist/unreal-bridge.js +4 -4
  80. package/dist/utils/command-validator.js +7 -5
  81. package/dist/utils/error-handler.d.ts +24 -2
  82. package/dist/utils/error-handler.js +58 -23
  83. package/dist/utils/normalize.d.ts +7 -4
  84. package/dist/utils/normalize.js +12 -10
  85. package/dist/utils/path-security.d.ts +2 -0
  86. package/dist/utils/path-security.js +24 -0
  87. package/dist/utils/response-factory.d.ts +4 -4
  88. package/dist/utils/response-factory.js +15 -21
  89. package/dist/utils/response-validator.js +88 -73
  90. package/dist/utils/unreal-command-queue.d.ts +2 -0
  91. package/dist/utils/unreal-command-queue.js +8 -1
  92. package/docs/Migration-Guide-v0.5.0.md +1 -9
  93. package/docs/handler-mapping.md +4 -2
  94. package/docs/testing-guide.md +2 -2
  95. package/package.json +12 -6
  96. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSubsystem.cpp +298 -33
  97. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AnimationHandlers.cpp +7 -8
  98. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintGraphHandlers.cpp +229 -319
  99. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers.cpp +98 -0
  100. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EffectHandlers.cpp +24 -0
  101. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EnvironmentHandlers.cpp +96 -0
  102. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LightingHandlers.cpp +52 -5
  103. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ProcessRequest.cpp +5 -268
  104. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequenceHandlers.cpp +57 -2
  105. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpConnectionManager.cpp +0 -1
  106. package/scripts/run-all-tests.mjs +25 -20
  107. package/server.json +3 -2
  108. package/src/automation/bridge.ts +27 -25
  109. package/src/automation/connection-manager.ts +18 -0
  110. package/src/automation/message-handler.ts +33 -8
  111. package/src/automation/request-tracker.ts +39 -7
  112. package/src/config.ts +1 -1
  113. package/src/constants.ts +7 -0
  114. package/src/graphql/loaders.ts +244 -0
  115. package/src/graphql/resolvers.ts +47 -49
  116. package/src/graphql/server.ts +3 -1
  117. package/src/graphql/types.ts +3 -0
  118. package/src/index.ts +15 -2
  119. package/src/resources/assets.ts +5 -4
  120. package/src/server/tool-registry.ts +3 -3
  121. package/src/server-setup.ts +3 -37
  122. package/src/tools/actors.ts +77 -44
  123. package/src/tools/animation.ts +1 -0
  124. package/src/tools/assets.ts +76 -65
  125. package/src/tools/base-tool.ts +3 -3
  126. package/src/tools/blueprint.ts +170 -104
  127. package/src/tools/consolidated-tool-definitions.ts +2 -1
  128. package/src/tools/consolidated-tool-handlers.ts +129 -150
  129. package/src/tools/dynamic-handler-registry.ts +22 -140
  130. package/src/tools/editor.ts +43 -29
  131. package/src/tools/environment.ts +21 -27
  132. package/src/tools/foliage.ts +28 -25
  133. package/src/tools/handlers/actor-handlers.ts +16 -17
  134. package/src/tools/handlers/asset-handlers.ts +484 -484
  135. package/src/tools/handlers/sequence-handlers.ts +85 -62
  136. package/src/tools/introspection.ts +7 -7
  137. package/src/tools/landscape.ts +34 -28
  138. package/src/tools/level.ts +100 -80
  139. package/src/tools/lighting.ts +25 -20
  140. package/src/tools/materials.ts +9 -3
  141. package/src/tools/niagara.ts +44 -2
  142. package/src/tools/performance.ts +1 -2
  143. package/src/tools/physics.ts +7 -1
  144. package/src/tools/sequence.ts +42 -26
  145. package/src/tools/ui.ts +1 -3
  146. package/src/types/automation-responses.ts +119 -0
  147. package/src/types/responses.ts +355 -0
  148. package/src/types/tool-interfaces.ts +135 -135
  149. package/src/types/tool-types.ts +4 -0
  150. package/src/unreal-bridge.ts +71 -26
  151. package/src/utils/command-validator.ts +47 -5
  152. package/src/utils/error-handler.ts +128 -45
  153. package/src/utils/normalize.test.ts +162 -0
  154. package/src/utils/normalize.ts +38 -16
  155. package/src/utils/path-security.ts +43 -0
  156. package/src/utils/response-factory.ts +29 -24
  157. package/src/utils/response-validator.ts +103 -87
  158. package/src/utils/safe-json.test.ts +90 -0
  159. package/src/utils/unreal-command-queue.ts +13 -1
  160. package/src/utils/validation.test.ts +184 -0
  161. package/tests/test-animation.mjs +358 -33
  162. package/tests/test-asset-graph.mjs +311 -0
  163. package/tests/test-audio.mjs +314 -116
  164. package/tests/test-behavior-tree.mjs +327 -144
  165. package/tests/test-blueprint-graph.mjs +343 -12
  166. package/tests/test-control-editor.mjs +85 -53
  167. package/tests/test-graphql.mjs +58 -8
  168. package/tests/test-input.mjs +349 -0
  169. package/tests/test-inspect.mjs +291 -61
  170. package/tests/test-landscape.mjs +304 -48
  171. package/tests/test-lighting.mjs +428 -0
  172. package/tests/test-manage-level.mjs +70 -51
  173. package/tests/test-performance.mjs +539 -0
  174. package/tests/test-sequence.mjs +82 -46
  175. package/tests/test-system.mjs +72 -33
  176. package/tests/test-wasm.mjs +98 -8
  177. package/vitest.config.ts +35 -0
  178. package/.github/release-drafter.yml +0 -148
  179. package/dist/prompts/index.d.ts +0 -21
  180. package/dist/prompts/index.js +0 -217
  181. package/dist/tools/blueprint/helpers.d.ts +0 -29
  182. package/dist/tools/blueprint/helpers.js +0 -182
  183. package/src/prompts/index.ts +0 -249
  184. package/src/tools/blueprint/helpers.ts +0 -189
  185. package/tests/test-blueprint-events.mjs +0 -35
  186. package/tests/test-extra-tools.mjs +0 -38
  187. package/tests/test-render.mjs +0 -33
  188. package/tests/test-search-assets.mjs +0 -66
@@ -2,6 +2,22 @@ import { UnrealBridge } from '../unreal-bridge.js';
2
2
  import { ensureRotation, ensureVector3 } from '../utils/validation.js';
3
3
  import { BaseTool } from './base-tool.js';
4
4
  import { IActorTools, StandardActionResponse } from '../types/tool-interfaces.js';
5
+ import { ActorResponse } from '../types/automation-responses.js';
6
+ import { wasmIntegration } from '../wasm/index.js';
7
+
8
+ /** Extended actor response with spawn-specific fields */
9
+ interface SpawnActorResponse extends ActorResponse {
10
+ data?: {
11
+ name?: string;
12
+ objectPath?: string;
13
+ [key: string]: unknown;
14
+ };
15
+ actorName?: string;
16
+ actorPath?: string;
17
+ warnings?: string[];
18
+ details?: unknown[];
19
+ componentPaths?: string[];
20
+ }
5
21
 
6
22
  export class ActorTools extends BaseTool implements IActorTools {
7
23
  constructor(bridge: UnrealBridge) {
@@ -44,7 +60,7 @@ export class ActorTools extends BaseTool implements IActorTools {
44
60
  try {
45
61
  const bridge = this.getAutomationBridge();
46
62
  const timeoutMs = typeof params.timeoutMs === 'number' && params.timeoutMs > 0 ? params.timeoutMs : undefined;
47
- const response = await bridge.sendAutomationRequest(
63
+ const response = await bridge.sendAutomationRequest<SpawnActorResponse>(
48
64
  'control_actor',
49
65
  {
50
66
  action: 'spawn',
@@ -58,36 +74,39 @@ export class ActorTools extends BaseTool implements IActorTools {
58
74
  );
59
75
 
60
76
  if (!response || !response.success) {
61
- throw new Error(response?.error || response?.message || 'Failed to spawn actor');
77
+ const error = response?.error;
78
+ const errorObj = typeof error === 'object' && error !== null ? error as { message?: string } : null;
79
+ const errorMsg = typeof error === 'string' ? error : errorObj?.message || response?.message || 'Failed to spawn actor';
80
+ throw new Error(errorMsg);
62
81
  }
63
82
 
64
- const data = (response as any).data || {};
83
+ const data = response.data || {};
65
84
  const result: StandardActionResponse = {
66
85
  success: true,
67
86
  message: response.message || `Spawned actor ${className}`,
68
- actorName: data.name || (response as any).actorName,
69
- actorPath: data.objectPath || (response as any).actorPath,
87
+ actorName: data.name || response.actorName,
88
+ actorPath: data.objectPath || response.actorPath,
70
89
  resolvedClass: mappedClassPath,
71
90
  requestedClass: className,
72
91
  location: { x: locX, y: locY, z: locZ },
73
92
  rotation: { pitch: rotPitch, yaw: rotYaw, roll: rotRoll },
74
93
  data: data,
75
94
  actor: {
76
- name: data.name || (response as any).actorName,
77
- path: data.objectPath || (response as any).actorPath || mappedClassPath
95
+ name: data.name || response.actorName,
96
+ path: data.objectPath || response.actorPath || mappedClassPath
78
97
  }
79
98
  };
80
99
 
81
- if ((response as any).warnings?.length) {
82
- result.warnings = (response as any).warnings;
100
+ if (response.warnings?.length) {
101
+ result.warnings = response.warnings;
83
102
  }
84
103
 
85
104
  // Legacy support for older fields if they exist at top level
86
- if ((response as any).details?.length) {
87
- result.details = (response as any).details;
105
+ if (response.details?.length) {
106
+ result.details = response.details;
88
107
  }
89
- if ((response as any).componentPaths?.length) {
90
- result.componentPaths = (response as any).componentPaths;
108
+ if (response.componentPaths?.length) {
109
+ result.componentPaths = response.componentPaths;
91
110
  }
92
111
 
93
112
  return result;
@@ -117,7 +136,7 @@ export class ActorTools extends BaseTool implements IActorTools {
117
136
  // DELETE_PARTIAL as a handled, partial-success cleanup instead
118
137
  // of surfacing it as a hard error to the consolidated handler.
119
138
  const bridge = this.getAutomationBridge();
120
- const response: any = await bridge.sendAutomationRequest('control_actor', {
139
+ const response: any = await bridge.sendAutomationRequest<ActorResponse>('control_actor', {
121
140
  action: 'delete',
122
141
  actorNames: names
123
142
  });
@@ -158,7 +177,7 @@ export class ActorTools extends BaseTool implements IActorTools {
158
177
  throw new Error('Invalid actorName');
159
178
  }
160
179
 
161
- return this.sendRequest('delete', { actorName: params.actorName }, 'control_actor');
180
+ return this.sendRequest<StandardActionResponse>('delete', { actorName: params.actorName }, 'control_actor');
162
181
  }
163
182
 
164
183
  async applyForce(params: { actorName: string; force: { x: number; y: number; z: number } }) {
@@ -183,7 +202,7 @@ export class ActorTools extends BaseTool implements IActorTools {
183
202
  };
184
203
  }
185
204
 
186
- return this.sendRequest('apply_force', {
205
+ return this.sendRequest<StandardActionResponse>('apply_force', {
187
206
  actorName: params.actorName,
188
207
  force: { x: forceX, y: forceY, z: forceZ }
189
208
  }, 'control_actor');
@@ -259,7 +278,7 @@ export class ActorTools extends BaseTool implements IActorTools {
259
278
  if (location) payload.location = { x: location[0], y: location[1], z: location[2] };
260
279
  if (rotation) payload.rotation = { pitch: rotation[0], yaw: rotation[1], roll: rotation[2] };
261
280
 
262
- return this.sendRequest('spawn_blueprint', payload, 'control_actor');
281
+ return this.sendRequest<StandardActionResponse>('spawn_blueprint', payload, 'control_actor');
263
282
  }
264
283
 
265
284
  async setTransform(params: { actorName: string; location?: { x: number; y: number; z: number }; rotation?: { pitch: number; yaw: number; roll: number }; scale?: { x: number; y: number; z: number } }) {
@@ -282,19 +301,29 @@ export class ActorTools extends BaseTool implements IActorTools {
282
301
  payload.scale = { x: scl[0], y: scl[1], z: scl[2] };
283
302
  }
284
303
 
285
- return this.sendRequest('set_transform', payload, 'control_actor');
304
+ return this.sendRequest<StandardActionResponse>('set_transform', payload, 'control_actor');
286
305
  }
287
306
 
288
307
  async getTransform(actorName: string) {
289
308
  if (typeof actorName !== 'string' || actorName.trim().length === 0) {
290
309
  throw new Error('Invalid actorName');
291
310
  }
292
- return this.sendRequest('get_transform', { actorName }, 'control_actor')
293
- .then(response => {
294
- // If response is standardized, extract data or return as is.
295
- // For now, return the full response which includes data.
296
- return response;
297
- });
311
+ const response = await this.sendRequest<StandardActionResponse>('get_transform', { actorName }, 'control_actor');
312
+ if (!response.success) {
313
+ return { success: false, error: response.error || `Failed to get transform for actor ${actorName}` };
314
+ }
315
+
316
+ // Extract transform data from nested response (data.data or data or result)
317
+ const rawData: any = response.data ?? response.result ?? response;
318
+ const data: any = rawData?.data ?? rawData;
319
+
320
+ return {
321
+ success: true,
322
+ message: 'Transform retrieved',
323
+ location: data.location ?? data.Location,
324
+ rotation: data.rotation ?? data.Rotation,
325
+ scale: data.scale ?? data.Scale
326
+ };
298
327
  }
299
328
 
300
329
  async setVisibility(params: { actorName: string; visible: boolean }) {
@@ -302,7 +331,7 @@ export class ActorTools extends BaseTool implements IActorTools {
302
331
  if (!actorName) {
303
332
  throw new Error('Invalid actorName');
304
333
  }
305
- return this.sendRequest('set_visibility', { actorName, visible: Boolean(params.visible) }, 'control_actor');
334
+ return this.sendRequest<StandardActionResponse>('set_visibility', { actorName, visible: Boolean(params.visible) }, 'control_actor');
306
335
  }
307
336
 
308
337
  async addComponent(params: { actorName: string; componentType: string; componentName?: string; properties?: Record<string, unknown> }) {
@@ -311,7 +340,7 @@ export class ActorTools extends BaseTool implements IActorTools {
311
340
  if (!actorName) throw new Error('Invalid actorName');
312
341
  if (!componentType) throw new Error('Invalid componentType');
313
342
 
314
- return this.sendRequest('add_component', {
343
+ return this.sendRequest<StandardActionResponse>('add_component', {
315
344
  actorName,
316
345
  componentType,
317
346
  componentName: typeof params.componentName === 'string' ? params.componentName : undefined,
@@ -325,7 +354,7 @@ export class ActorTools extends BaseTool implements IActorTools {
325
354
  if (!actorName) throw new Error('Invalid actorName');
326
355
  if (!componentName) throw new Error('Invalid componentName');
327
356
 
328
- return this.sendRequest('set_component_properties', {
357
+ return this.sendRequest<StandardActionResponse>('set_component_properties', {
329
358
  actorName,
330
359
  componentName,
331
360
  properties: params.properties ?? {}
@@ -336,7 +365,7 @@ export class ActorTools extends BaseTool implements IActorTools {
336
365
  if (typeof actorName !== 'string' || actorName.trim().length === 0) {
337
366
  throw new Error('Invalid actorName');
338
367
  }
339
- const response = await this.sendRequest('get_components', { actorName }, 'control_actor');
368
+ const response = await this.sendRequest<StandardActionResponse>('get_components', { actorName }, 'control_actor');
340
369
  if (!response.success) {
341
370
  return { success: false, error: response.error || `Failed to get components for actor ${actorName}` };
342
371
  }
@@ -365,10 +394,14 @@ export class ActorTools extends BaseTool implements IActorTools {
365
394
  }
366
395
  if (params.offset) {
367
396
  const offs = ensureVector3(params.offset, 'duplicate offset');
368
- payload.offset = { x: offs[0], y: offs[1], z: offs[2] };
397
+ // Use WASM vectorAdd for offset calculation (origin + offset)
398
+ const origin: [number, number, number] = [0, 0, 0];
399
+ const calculatedOffset = wasmIntegration.vectorAdd(origin, offs);
400
+ console.error('[WASM] Using vectorAdd for duplicate offset calculation');
401
+ payload.offset = { x: calculatedOffset[0], y: calculatedOffset[1], z: calculatedOffset[2] };
369
402
  }
370
403
 
371
- return this.sendRequest('duplicate', payload, 'control_actor');
404
+ return this.sendRequest<StandardActionResponse>('duplicate', payload, 'control_actor');
372
405
  }
373
406
 
374
407
  async addTag(params: { actorName: string; tag: string }) {
@@ -377,7 +410,7 @@ export class ActorTools extends BaseTool implements IActorTools {
377
410
  if (!actorName) throw new Error('Invalid actorName');
378
411
  if (!tag) throw new Error('Invalid tag');
379
412
 
380
- return this.sendRequest('add_tag', { actorName, tag }, 'control_actor');
413
+ return this.sendRequest<StandardActionResponse>('add_tag', { actorName, tag }, 'control_actor');
381
414
  }
382
415
 
383
416
  async removeTag(params: { actorName: string; tag: string }) {
@@ -386,7 +419,7 @@ export class ActorTools extends BaseTool implements IActorTools {
386
419
  if (!actorName) throw new Error('Invalid actorName');
387
420
  if (!tag) throw new Error('Invalid tag');
388
421
 
389
- return this.sendRequest('remove_tag', { actorName, tag }, 'control_actor');
422
+ return this.sendRequest<StandardActionResponse>('remove_tag', { actorName, tag }, 'control_actor');
390
423
  }
391
424
 
392
425
  async findByTag(params: { tag: string; matchType?: string }) {
@@ -404,7 +437,7 @@ export class ActorTools extends BaseTool implements IActorTools {
404
437
  };
405
438
  }
406
439
 
407
- return this.sendRequest('find_by_tag', {
440
+ return this.sendRequest<StandardActionResponse>('find_by_tag', {
408
441
  tag,
409
442
  matchType: typeof params.matchType === 'string' ? params.matchType : undefined
410
443
  }, 'control_actor');
@@ -414,7 +447,7 @@ export class ActorTools extends BaseTool implements IActorTools {
414
447
  if (typeof name !== 'string' || name.trim().length === 0) {
415
448
  throw new Error('Invalid actor name query');
416
449
  }
417
- return this.sendRequest('find_by_name', { name: name.trim() }, 'control_actor');
450
+ return this.sendRequest<StandardActionResponse>('find_by_name', { name: name.trim() }, 'control_actor');
418
451
  }
419
452
 
420
453
  async detach(actorName: string) {
@@ -428,7 +461,7 @@ export class ActorTools extends BaseTool implements IActorTools {
428
461
  if (typeof actorName !== 'string' || actorName.trim().length === 0) {
429
462
  throw new Error('Invalid actorName');
430
463
  }
431
- return this.sendRequest('detach', { actorName }, 'control_actor');
464
+ return this.sendRequest<StandardActionResponse>('detach', { actorName }, 'control_actor');
432
465
  }
433
466
 
434
467
  async attach(params: { childActor: string; parentActor: string }) {
@@ -437,20 +470,20 @@ export class ActorTools extends BaseTool implements IActorTools {
437
470
  if (!child) throw new Error('Invalid childActor');
438
471
  if (!parent) throw new Error('Invalid parentActor');
439
472
 
440
- return this.sendRequest('attach', { childActor: child, parentActor: parent }, 'control_actor');
473
+ return this.sendRequest<StandardActionResponse>('attach', { childActor: child, parentActor: parent }, 'control_actor');
441
474
  }
442
475
 
443
476
  async deleteByTag(tag: string) {
444
477
  if (typeof tag !== 'string' || tag.trim().length === 0) {
445
478
  throw new Error('Invalid tag');
446
479
  }
447
- return this.sendRequest('delete_by_tag', { tag: tag.trim() }, 'control_actor');
480
+ return this.sendRequest<StandardActionResponse>('delete_by_tag', { tag: tag.trim() }, 'control_actor');
448
481
  }
449
482
 
450
483
  async setBlueprintVariables(params: { actorName: string; variables: Record<string, unknown> }) {
451
484
  const actorName = typeof params.actorName === 'string' ? params.actorName.trim() : '';
452
485
  if (!actorName) throw new Error('Invalid actorName');
453
- return this.sendRequest('set_blueprint_variables', { actorName, variables: params.variables ?? {} }, 'control_actor');
486
+ return this.sendRequest<StandardActionResponse>('set_blueprint_variables', { actorName, variables: params.variables ?? {} }, 'control_actor');
454
487
  }
455
488
 
456
489
  async createSnapshot(params: { actorName: string; snapshotName: string }) {
@@ -458,7 +491,7 @@ export class ActorTools extends BaseTool implements IActorTools {
458
491
  const snapshotName = typeof params.snapshotName === 'string' ? params.snapshotName.trim() : '';
459
492
  if (!actorName) throw new Error('Invalid actorName');
460
493
  if (!snapshotName) throw new Error('Invalid snapshotName');
461
- return this.sendRequest('create_snapshot', { actorName, snapshotName }, 'control_actor');
494
+ return this.sendRequest<StandardActionResponse>('create_snapshot', { actorName, snapshotName }, 'control_actor');
462
495
  }
463
496
 
464
497
  async restoreSnapshot(params: { actorName: string; snapshotName: string }) {
@@ -466,12 +499,12 @@ export class ActorTools extends BaseTool implements IActorTools {
466
499
  const snapshotName = typeof params.snapshotName === 'string' ? params.snapshotName.trim() : '';
467
500
  if (!actorName) throw new Error('Invalid actorName');
468
501
  if (!snapshotName) throw new Error('Invalid snapshotName');
469
- return this.sendRequest('restore_snapshot', { actorName, snapshotName }, 'control_actor');
502
+ return this.sendRequest<StandardActionResponse>('restore_snapshot', { actorName, snapshotName }, 'control_actor');
470
503
  }
471
504
  async exportActor(params: { actorName: string; destinationPath?: string }) {
472
505
  const actorName = typeof params.actorName === 'string' ? params.actorName.trim() : '';
473
506
  if (!actorName) throw new Error('Invalid actorName');
474
- return this.sendRequest('export', {
507
+ return this.sendRequest<StandardActionResponse>('export', {
475
508
  actorName,
476
509
  destinationPath: params.destinationPath
477
510
  }, 'control_actor');
@@ -481,7 +514,7 @@ export class ActorTools extends BaseTool implements IActorTools {
481
514
  if (typeof actorName !== 'string' || actorName.trim().length === 0) {
482
515
  throw new Error('Invalid actorName');
483
516
  }
484
- const response = await this.sendRequest('get_bounding_box', { actorName }, 'control_actor');
517
+ const response = await this.sendRequest<StandardActionResponse>('get_bounding_box', { actorName }, 'control_actor');
485
518
  if (!response.success) {
486
519
  return { success: false, error: response.error || `Failed to get bounding box for actor ${actorName}` };
487
520
  }
@@ -496,7 +529,7 @@ export class ActorTools extends BaseTool implements IActorTools {
496
529
  if (typeof actorName !== 'string' || actorName.trim().length === 0) {
497
530
  throw new Error('Invalid actorName');
498
531
  }
499
- const response = await this.sendRequest('get_metadata', { actorName }, 'control_actor');
532
+ const response = await this.sendRequest<StandardActionResponse>('get_metadata', { actorName }, 'control_actor');
500
533
  if (!response.success) {
501
534
  return { success: false, error: response.error || `Failed to get metadata for actor ${actorName}` };
502
535
  }
@@ -512,7 +545,7 @@ export class ActorTools extends BaseTool implements IActorTools {
512
545
  if (params?.filter) {
513
546
  payload.filter = params.filter;
514
547
  }
515
- const response = await this.sendRequest('list_actors', payload, 'control_actor');
548
+ const response = await this.sendRequest<StandardActionResponse>('list_actors', payload, 'control_actor');
516
549
  if (!response.success) {
517
550
  return { success: false, error: response.error || 'Failed to list actors' };
518
551
  }
@@ -2,6 +2,7 @@ import { UnrealBridge } from '../unreal-bridge.js';
2
2
  import { AutomationBridge } from '../automation/index.js';
3
3
  import { cleanObject } from '../utils/safe-json.js';
4
4
  import { validateAssetParams } from '../utils/validation.js';
5
+ import { wasmIntegration as _wasmIntegration } from '../wasm/index.js';
5
6
 
6
7
  type CreateAnimationBlueprintSuccess = {
7
8
  success: true;