unreal-engine-mcp-server 0.5.0 → 0.5.1

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 (139) 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 +1 -0
  6. package/.github/workflows/release-drafter.yml +1 -1
  7. package/.github/workflows/release.yml +3 -3
  8. package/CHANGELOG.md +71 -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/config.d.ts +0 -1
  14. package/dist/config.js +0 -1
  15. package/dist/constants.d.ts +4 -0
  16. package/dist/constants.js +4 -0
  17. package/dist/graphql/loaders.d.ts +64 -0
  18. package/dist/graphql/loaders.js +117 -0
  19. package/dist/graphql/resolvers.d.ts +3 -3
  20. package/dist/graphql/resolvers.js +33 -30
  21. package/dist/graphql/server.js +3 -1
  22. package/dist/graphql/types.d.ts +2 -0
  23. package/dist/index.d.ts +2 -0
  24. package/dist/index.js +13 -2
  25. package/dist/server-setup.d.ts +0 -1
  26. package/dist/server-setup.js +0 -40
  27. package/dist/tools/actors.d.ts +40 -24
  28. package/dist/tools/actors.js +8 -2
  29. package/dist/tools/assets.d.ts +19 -71
  30. package/dist/tools/assets.js +28 -22
  31. package/dist/tools/base-tool.d.ts +4 -4
  32. package/dist/tools/base-tool.js +1 -1
  33. package/dist/tools/blueprint.d.ts +33 -61
  34. package/dist/tools/consolidated-tool-handlers.js +96 -110
  35. package/dist/tools/dynamic-handler-registry.d.ts +11 -9
  36. package/dist/tools/dynamic-handler-registry.js +17 -95
  37. package/dist/tools/editor.d.ts +19 -193
  38. package/dist/tools/editor.js +8 -0
  39. package/dist/tools/environment.d.ts +8 -14
  40. package/dist/tools/foliage.d.ts +18 -143
  41. package/dist/tools/foliage.js +4 -2
  42. package/dist/tools/handlers/actor-handlers.js +0 -5
  43. package/dist/tools/handlers/asset-handlers.js +454 -454
  44. package/dist/tools/landscape.d.ts +16 -116
  45. package/dist/tools/landscape.js +7 -3
  46. package/dist/tools/level.d.ts +22 -103
  47. package/dist/tools/level.js +24 -16
  48. package/dist/tools/lighting.js +5 -1
  49. package/dist/tools/materials.js +5 -1
  50. package/dist/tools/niagara.js +37 -2
  51. package/dist/tools/performance.d.ts +0 -1
  52. package/dist/tools/performance.js +0 -1
  53. package/dist/tools/physics.js +5 -1
  54. package/dist/tools/sequence.d.ts +24 -24
  55. package/dist/tools/sequence.js +13 -0
  56. package/dist/tools/ui.d.ts +0 -2
  57. package/dist/types/automation-responses.d.ts +115 -0
  58. package/dist/types/automation-responses.js +2 -0
  59. package/dist/types/responses.d.ts +249 -0
  60. package/dist/types/responses.js +2 -0
  61. package/dist/types/tool-interfaces.d.ts +135 -135
  62. package/dist/utils/command-validator.js +3 -2
  63. package/dist/utils/path-security.d.ts +2 -0
  64. package/dist/utils/path-security.js +24 -0
  65. package/dist/utils/response-factory.d.ts +4 -4
  66. package/dist/utils/response-factory.js +15 -21
  67. package/docs/Migration-Guide-v0.5.0.md +1 -9
  68. package/docs/testing-guide.md +2 -2
  69. package/package.json +12 -6
  70. package/scripts/run-all-tests.mjs +25 -20
  71. package/server.json +3 -2
  72. package/src/config.ts +1 -1
  73. package/src/constants.ts +7 -0
  74. package/src/graphql/loaders.ts +244 -0
  75. package/src/graphql/resolvers.ts +47 -49
  76. package/src/graphql/server.ts +3 -1
  77. package/src/graphql/types.ts +3 -0
  78. package/src/index.ts +15 -2
  79. package/src/resources/assets.ts +5 -4
  80. package/src/server-setup.ts +3 -37
  81. package/src/tools/actors.ts +36 -28
  82. package/src/tools/animation.ts +1 -0
  83. package/src/tools/assets.ts +74 -63
  84. package/src/tools/base-tool.ts +3 -3
  85. package/src/tools/blueprint.ts +59 -59
  86. package/src/tools/consolidated-tool-handlers.ts +129 -150
  87. package/src/tools/dynamic-handler-registry.ts +22 -140
  88. package/src/tools/editor.ts +39 -26
  89. package/src/tools/environment.ts +21 -27
  90. package/src/tools/foliage.ts +28 -25
  91. package/src/tools/handlers/actor-handlers.ts +2 -8
  92. package/src/tools/handlers/asset-handlers.ts +484 -484
  93. package/src/tools/handlers/sequence-handlers.ts +1 -1
  94. package/src/tools/landscape.ts +34 -28
  95. package/src/tools/level.ts +96 -76
  96. package/src/tools/lighting.ts +6 -1
  97. package/src/tools/materials.ts +8 -2
  98. package/src/tools/niagara.ts +44 -2
  99. package/src/tools/performance.ts +1 -2
  100. package/src/tools/physics.ts +7 -1
  101. package/src/tools/sequence.ts +41 -25
  102. package/src/tools/ui.ts +0 -2
  103. package/src/types/automation-responses.ts +119 -0
  104. package/src/types/responses.ts +355 -0
  105. package/src/types/tool-interfaces.ts +135 -135
  106. package/src/utils/command-validator.ts +3 -2
  107. package/src/utils/normalize.test.ts +162 -0
  108. package/src/utils/path-security.ts +43 -0
  109. package/src/utils/response-factory.ts +29 -24
  110. package/src/utils/safe-json.test.ts +90 -0
  111. package/src/utils/validation.test.ts +184 -0
  112. package/tests/test-animation.mjs +358 -33
  113. package/tests/test-asset-graph.mjs +311 -0
  114. package/tests/test-audio.mjs +314 -116
  115. package/tests/test-behavior-tree.mjs +327 -144
  116. package/tests/test-blueprint-graph.mjs +343 -12
  117. package/tests/test-control-editor.mjs +85 -53
  118. package/tests/test-graphql.mjs +58 -8
  119. package/tests/test-input.mjs +349 -0
  120. package/tests/test-inspect.mjs +291 -61
  121. package/tests/test-landscape.mjs +304 -48
  122. package/tests/test-lighting.mjs +428 -0
  123. package/tests/test-manage-level.mjs +70 -51
  124. package/tests/test-performance.mjs +539 -0
  125. package/tests/test-sequence.mjs +82 -46
  126. package/tests/test-system.mjs +72 -33
  127. package/tests/test-wasm.mjs +98 -8
  128. package/vitest.config.ts +35 -0
  129. package/.github/release-drafter.yml +0 -148
  130. package/dist/prompts/index.d.ts +0 -21
  131. package/dist/prompts/index.js +0 -217
  132. package/dist/tools/blueprint/helpers.d.ts +0 -29
  133. package/dist/tools/blueprint/helpers.js +0 -182
  134. package/src/prompts/index.ts +0 -249
  135. package/src/tools/blueprint/helpers.ts +0 -189
  136. package/tests/test-blueprint-events.mjs +0 -35
  137. package/tests/test-extra-tools.mjs +0 -38
  138. package/tests/test-render.mjs +0 -33
  139. package/tests/test-search-assets.mjs +0 -66
@@ -1,6 +1,7 @@
1
1
  import { UnrealBridge } from '../unreal-bridge.js';
2
2
  import { AutomationBridge } from '../automation/index.js';
3
3
  import { sanitizeAssetName, validateAssetParams } from '../utils/validation.js';
4
+ import { wasmIntegration } from '../wasm/index.js';
4
5
 
5
6
  type Vector3 = [number, number, number];
6
7
 
@@ -30,6 +31,18 @@ export class NiagaraTools {
30
31
  throw new Error('Automation Bridge not available. Niagara system creation requires plugin support.');
31
32
  }
32
33
 
34
+ // Process emitter params with WASM
35
+ if (params.emitters) {
36
+ for (const emitter of params.emitters) {
37
+ if (emitter.shapeSize) {
38
+ const zeroVector: [number, number, number] = [0, 0, 0];
39
+ const processedSize = wasmIntegration.vectorAdd(zeroVector, emitter.shapeSize);
40
+ console.error('[WASM] Using vectorAdd for Niagara emitter shape size');
41
+ emitter.shapeSize = [processedSize[0], processedSize[1], processedSize[2]];
42
+ }
43
+ }
44
+ }
45
+
33
46
  const path = params.savePath || '/Game/Effects/Niagara';
34
47
  const response: any = await this.automationBridge.sendAutomationRequest(
35
48
  'create_niagara_system',
@@ -118,8 +131,22 @@ export class NiagaraTools {
118
131
  };
119
132
 
120
133
  const requestPayload: Record<string, unknown> = { systemPath: params.systemPath };
121
- const start = toVector(params.start);
122
- const end = toVector(params.end);
134
+ let start = toVector(params.start);
135
+ let end = toVector(params.end);
136
+
137
+ // Use WASM for vector processing if available
138
+ const zeroVector: [number, number, number] = [0, 0, 0];
139
+ if (start) {
140
+ const processed = wasmIntegration.vectorAdd(zeroVector, start);
141
+ console.error('[WASM] Using vectorAdd for Niagara ribbon start');
142
+ start = [processed[0], processed[1], processed[2]];
143
+ }
144
+ if (end) {
145
+ const processed = wasmIntegration.vectorAdd(zeroVector, end);
146
+ console.error('[WASM] Using vectorAdd for Niagara ribbon end');
147
+ end = [processed[0], processed[1], processed[2]];
148
+ }
149
+
123
150
  if (start) requestPayload.start = start;
124
151
  if (end) requestPayload.end = end;
125
152
  if (params.color) requestPayload.color = params.color;
@@ -202,6 +229,21 @@ export class NiagaraTools {
202
229
  return { success: false, error: 'AUTOMATION_BRIDGE_UNAVAILABLE', message: 'addEmitter requires automation bridge' } as const;
203
230
  }
204
231
 
232
+ // Use WASM for velocity processing
233
+ if (params.properties) {
234
+ const zeroVector: [number, number, number] = [0, 0, 0];
235
+ if (params.properties.velocityMin) {
236
+ const processed = wasmIntegration.vectorAdd(zeroVector, params.properties.velocityMin);
237
+ console.error('[WASM] Using vectorAdd for Niagara velocity min');
238
+ params.properties.velocityMin = [processed[0], processed[1], processed[2]];
239
+ }
240
+ if (params.properties.velocityMax) {
241
+ const processed = wasmIntegration.vectorAdd(zeroVector, params.properties.velocityMax);
242
+ console.error('[WASM] Using vectorAdd for Niagara velocity max');
243
+ params.properties.velocityMax = [processed[0], processed[1], processed[2]];
244
+ }
245
+ }
246
+
205
247
  try {
206
248
  const resp: any = await this.automationBridge.sendAutomationRequest('manage_niagara_graph', {
207
249
  subAction: 'add_emitter',
@@ -474,7 +474,7 @@ export class PerformanceTools {
474
474
  // Draw call optimization
475
475
  async optimizeDrawCalls(params: {
476
476
  enableInstancing?: boolean;
477
- enableBatching?: boolean; // no-op (deprecated internal toggle)
477
+
478
478
  mergeActors?: boolean;
479
479
  actors?: string[];
480
480
  }) {
@@ -495,7 +495,6 @@ export class PerformanceTools {
495
495
 
496
496
  const payload: any = {
497
497
  enableInstancing: params.enableInstancing,
498
- enableBatching: params.enableBatching,
499
498
  mergeActors: params.mergeActors,
500
499
  actors: actors
501
500
  };
@@ -3,6 +3,7 @@ import { UnrealBridge } from '../unreal-bridge.js';
3
3
  import { AutomationBridge } from '../automation/index.js';
4
4
  import { validateAssetParams, resolveSkeletalMeshPath, concurrencyDelay } from '../utils/validation.js';
5
5
  import { coerceString, coerceStringArray } from '../utils/result-helpers.js';
6
+ import { wasmIntegration } from '../wasm/index.js';
6
7
 
7
8
  export class PhysicsTools {
8
9
  constructor(private bridge: UnrealBridge, private automationBridge?: AutomationBridge) { }
@@ -485,10 +486,15 @@ export class PhysicsTools {
485
486
  }
486
487
 
487
488
  try {
489
+ // Use WASM for vector normalization/validation
490
+ const zeroVector: [number, number, number] = [0, 0, 0];
491
+ const normalizedVector = wasmIntegration.vectorAdd(zeroVector, params.vector);
492
+ console.error('[WASM] Using vectorAdd for physics force vector processing');
493
+
488
494
  const response = await this.automationBridge.sendAutomationRequest('apply_force', {
489
495
  actorName: params.actorName,
490
496
  forceType: params.forceType,
491
- vector: params.vector,
497
+ vector: normalizedVector,
492
498
  boneName: params.boneName,
493
499
  isLocal: params.isLocal
494
500
  }, {
@@ -1,5 +1,7 @@
1
1
  import { BaseTool } from './base-tool.js';
2
- import { ISequenceTools } from '../types/tool-interfaces.js';
2
+ import { ISequenceTools, StandardActionResponse } from '../types/tool-interfaces.js';
3
+ import { SequenceResponse } from '../types/automation-responses.js';
4
+ import { wasmIntegration } from '../wasm/index.js';
3
5
 
4
6
  export interface LevelSequence {
5
7
  path: string;
@@ -39,7 +41,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
39
41
  const finalTimeout = typeof timeoutMs === 'number' && timeoutMs > 0 ? timeoutMs : defaultTimeout;
40
42
 
41
43
  try {
42
- const response = await this.sendAutomationRequest(
44
+ const response = await this.sendAutomationRequest<SequenceResponse>(
43
45
  action,
44
46
  payload,
45
47
  { timeoutMs: finalTimeout, waitForEvent: false }
@@ -61,7 +63,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
61
63
  return txt.includes('unknown_action') || txt.includes('unknown automation action') || txt.includes('not_implemented') || txt === 'unknown_plugin_action';
62
64
  }
63
65
 
64
- async create(params: { name: string; path?: string; timeoutMs?: number }) {
66
+ async create(params: { name: string; path?: string; timeoutMs?: number }): Promise<StandardActionResponse> {
65
67
  const name = params.name?.trim();
66
68
  const base = (params.path || '/Game/Sequences').replace(/\/$/, '');
67
69
  if (!name) return { success: false, error: 'name is required' };
@@ -79,7 +81,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
79
81
  return resp;
80
82
  }
81
83
 
82
- async open(params: { path: string }) {
84
+ async open(params: { path: string }): Promise<StandardActionResponse> {
83
85
  const path = params.path?.trim();
84
86
  const resp = await this.sendAction('sequence_open', { path });
85
87
  if (!resp.success && this.isUnknownActionResponse(resp)) {
@@ -91,7 +93,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
91
93
  return resp;
92
94
  }
93
95
 
94
- async addCamera(params: { spawnable?: boolean; path?: string }) {
96
+ async addCamera(params: { spawnable?: boolean; path?: string }): Promise<StandardActionResponse> {
95
97
  const path = this.resolveSequencePath(params.path);
96
98
  const resp = await this.sendAction('sequence_add_camera', { path, spawnable: params.spawnable !== false });
97
99
  if (!resp.success && this.isUnknownActionResponse(resp)) {
@@ -100,7 +102,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
100
102
  return resp;
101
103
  }
102
104
 
103
- async addActor(params: { actorName: string; createBinding?: boolean; path?: string }) {
105
+ async addActor(params: { actorName: string; createBinding?: boolean; path?: string }): Promise<StandardActionResponse> {
104
106
  const path = this.resolveSequencePath(params.path);
105
107
  const resp = await this.sendAction('sequence_add_actor', { path, actorName: params.actorName, createBinding: params.createBinding });
106
108
  if (!resp.success && this.isUnknownActionResponse(resp)) {
@@ -112,7 +114,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
112
114
  /**
113
115
  * Play the current level sequence
114
116
  */
115
- async play(params?: { path?: string; startTime?: number; loopMode?: 'once' | 'loop' | 'pingpong' }) {
117
+ async play(params?: { path?: string; startTime?: number; loopMode?: 'once' | 'loop' | 'pingpong' }): Promise<StandardActionResponse> {
116
118
  const path = this.resolveSequencePath(params?.path);
117
119
  const resp = await this.sendAction('sequence_play', { path, startTime: params?.startTime, loopMode: params?.loopMode });
118
120
  if (!resp.success && this.isUnknownActionResponse(resp)) {
@@ -124,7 +126,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
124
126
  /**
125
127
  * Pause the current level sequence
126
128
  */
127
- async pause(params?: { path?: string }) {
129
+ async pause(params?: { path?: string }): Promise<StandardActionResponse> {
128
130
  const path = this.resolveSequencePath(params?.path);
129
131
  const resp = await this.sendAction('sequence_pause', { path });
130
132
  if (!resp.success && this.isUnknownActionResponse(resp)) {
@@ -136,7 +138,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
136
138
  /**
137
139
  * Stop/close the current level sequence
138
140
  */
139
- async stop(params?: { path?: string }) {
141
+ async stop(params?: { path?: string }): Promise<StandardActionResponse> {
140
142
  const path = this.resolveSequencePath(params?.path);
141
143
  const resp = await this.sendAction('sequence_stop', { path });
142
144
  if (!resp.success && this.isUnknownActionResponse(resp)) {
@@ -154,7 +156,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
154
156
  lengthInFrames?: number;
155
157
  playbackStart?: number;
156
158
  playbackEnd?: number;
157
- }) {
159
+ }): Promise<StandardActionResponse> {
158
160
  const payload: Record<string, unknown> = {
159
161
  path: params.path,
160
162
  frameRate: params.frameRate,
@@ -172,7 +174,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
172
174
  /**
173
175
  * Set display rate (fps)
174
176
  */
175
- async setDisplayRate(params: { path?: string; frameRate: string | number }) {
177
+ async setDisplayRate(params: { path?: string; frameRate: string | number }): Promise<StandardActionResponse> {
176
178
  const resp = await this.sendAction('sequence_set_display_rate', { path: params.path, frameRate: params.frameRate });
177
179
  if (!resp.success && this.isUnknownActionResponse(resp)) {
178
180
  return { success: false, error: 'UNKNOWN_PLUGIN_ACTION', message: 'Automation plugin does not implement sequence_set_display_rate' } as const;
@@ -183,7 +185,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
183
185
  /**
184
186
  * Get sequence properties
185
187
  */
186
- async getSequenceProperties(params: { path?: string }) {
188
+ async getSequenceProperties(params: { path?: string }): Promise<StandardActionResponse> {
187
189
  const resp = await this.sendAction('sequence_get_properties', { path: params.path });
188
190
  if (!resp.success && this.isUnknownActionResponse(resp)) {
189
191
  return { success: false, error: 'UNKNOWN_PLUGIN_ACTION', message: 'Automation plugin does not implement sequence_get_properties' } as const;
@@ -194,7 +196,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
194
196
  /**
195
197
  * Set playback speed/rate
196
198
  */
197
- async setPlaybackSpeed(params: { speed: number; path?: string }) {
199
+ async setPlaybackSpeed(params: { speed: number; path?: string }): Promise<StandardActionResponse> {
198
200
  const path = this.resolveSequencePath(params.path);
199
201
  const resp = await this.sendAction('sequence_set_playback_speed', { path, speed: params.speed });
200
202
  if (!resp.success && this.isUnknownActionResponse(resp)) {
@@ -206,7 +208,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
206
208
  /**
207
209
  * Get all bindings in the current sequence
208
210
  */
209
- async getBindings(params?: { path?: string }) {
211
+ async getBindings(params?: { path?: string }): Promise<StandardActionResponse> {
210
212
  const resp = await this.sendAction('sequence_get_bindings', { path: params?.path });
211
213
  if (!resp.success && this.isUnknownActionResponse(resp)) {
212
214
  return { success: false, error: 'UNKNOWN_PLUGIN_ACTION', message: 'Automation plugin does not implement sequence_get_bindings' } as const;
@@ -217,7 +219,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
217
219
  /**
218
220
  * Add multiple actors to sequence at once
219
221
  */
220
- async addActors(params: { actorNames: string[]; path?: string }) {
222
+ async addActors(params: { actorNames: string[]; path?: string }): Promise<StandardActionResponse> {
221
223
  const path = this.resolveSequencePath(params.path);
222
224
  const resp = await this.sendAction('sequence_add_actors', { path, actorNames: params.actorNames });
223
225
  if (!resp.success && this.isUnknownActionResponse(resp)) {
@@ -229,7 +231,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
229
231
  /**
230
232
  * Remove actors from binding
231
233
  */
232
- async removeActors(params: { actorNames: string[]; path?: string }) {
234
+ async removeActors(params: { actorNames: string[]; path?: string }): Promise<StandardActionResponse> {
233
235
  const path = this.resolveSequencePath(params.path);
234
236
  const resp = await this.sendAction('sequence_remove_actors', { path, actorNames: params.actorNames });
235
237
  if (!resp.success && this.isUnknownActionResponse(resp)) {
@@ -241,7 +243,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
241
243
  /**
242
244
  * Create a spawnable from an actor class
243
245
  */
244
- async addSpawnableFromClass(params: { className: string; path?: string }) {
246
+ async addSpawnableFromClass(params: { className: string; path?: string }): Promise<StandardActionResponse> {
245
247
  const resp = await this.sendAction('sequence_add_spawnable_from_class', { className: params.className, path: params.path });
246
248
  if (!resp.success && this.isUnknownActionResponse(resp)) {
247
249
  return { success: false, error: 'UNKNOWN_PLUGIN_ACTION', message: 'Automation plugin does not implement sequence_add_spawnable_from_class' } as const;
@@ -249,7 +251,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
249
251
  return resp;
250
252
  }
251
253
 
252
- async list(params?: { path?: string }) {
254
+ async list(params?: { path?: string }): Promise<StandardActionResponse> {
253
255
  const resp = await this.sendAction('sequence_list', { path: params?.path });
254
256
  if (!resp.success && this.isUnknownActionResponse(resp)) {
255
257
  return { success: false, error: 'UNKNOWN_PLUGIN_ACTION', message: 'Automation plugin does not implement sequence_list' } as const;
@@ -265,7 +267,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
265
267
  return resp;
266
268
  }
267
269
 
268
- async duplicate(params: { path: string; destinationPath: string }) {
270
+ async duplicate(params: { path: string; destinationPath: string }): Promise<StandardActionResponse> {
269
271
  const resp = await this.sendAction('sequence_duplicate', { path: params.path, destinationPath: params.destinationPath });
270
272
  if (!resp.success && this.isUnknownActionResponse(resp)) {
271
273
  return { success: false, error: 'UNKNOWN_PLUGIN_ACTION', message: 'Automation plugin does not implement sequence_duplicate' } as const;
@@ -273,7 +275,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
273
275
  return resp;
274
276
  }
275
277
 
276
- async rename(params: { path: string; newName: string }) {
278
+ async rename(params: { path: string; newName: string }): Promise<StandardActionResponse> {
277
279
  const resp = await this.sendAction('sequence_rename', { path: params.path, newName: params.newName });
278
280
  if (!resp.success && this.isUnknownActionResponse(resp)) {
279
281
  return { success: false, error: 'UNKNOWN_PLUGIN_ACTION', message: 'Automation plugin does not implement sequence_rename' } as const;
@@ -281,7 +283,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
281
283
  return resp;
282
284
  }
283
285
 
284
- async deleteSequence(params: { path: string }) {
286
+ async deleteSequence(params: { path: string }): Promise<StandardActionResponse> {
285
287
  const resp = await this.sendAction('sequence_delete', { path: params.path });
286
288
  if (!resp.success && this.isUnknownActionResponse(resp)) {
287
289
  return { success: false, error: 'UNKNOWN_PLUGIN_ACTION', message: 'Automation plugin does not implement sequence_delete' } as const;
@@ -289,7 +291,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
289
291
  return resp;
290
292
  }
291
293
 
292
- async getMetadata(params: { path?: string }) {
294
+ async getMetadata(params: { path?: string }): Promise<StandardActionResponse> {
293
295
  const resp = await this.sendAction('sequence_get_metadata', { path: params.path });
294
296
  if (!resp.success && this.isUnknownActionResponse(resp)) {
295
297
  return { success: false, error: 'UNKNOWN_PLUGIN_ACTION', message: 'Automation plugin does not implement sequence_get_metadata' } as const;
@@ -311,7 +313,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
311
313
  rotation?: { roll: number; pitch: number; yaw: number };
312
314
  scale?: { x: number; y: number; z: number };
313
315
  };
314
- }) {
316
+ }): Promise<StandardActionResponse> {
315
317
  const resp = await this.sendAction('sequence_add_keyframe', {
316
318
  path: params.path,
317
319
  bindingId: params.bindingId,
@@ -320,6 +322,20 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
320
322
  frame: params.frame,
321
323
  value: params.value
322
324
  });
325
+
326
+ // Use WASM for transform processing
327
+ if (params.property === 'Transform' && params.value) {
328
+ const loc = params.value.location;
329
+ const rot = params.value.rotation;
330
+ const scale = params.value.scale;
331
+ if (loc && rot && scale) {
332
+ const locArr: [number, number, number] = [loc.x, loc.y, loc.z];
333
+ const rotArr: [number, number, number] = [rot.pitch, rot.yaw, rot.roll];
334
+ const scaleArr: [number, number, number] = [scale.x, scale.y, scale.z];
335
+ wasmIntegration.composeTransform(locArr, rotArr, scaleArr);
336
+ console.error('[WASM] Using composeTransform for keyframe validation');
337
+ }
338
+ }
323
339
  if (!resp.success && this.isUnknownActionResponse(resp)) {
324
340
  return { success: false, error: 'UNKNOWN_PLUGIN_ACTION', message: 'Automation plugin does not implement sequence_add_keyframe' } as const;
325
341
  }
@@ -329,7 +345,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
329
345
  /**
330
346
  * List tracks in a sequence
331
347
  */
332
- async listTracks(params: { path: string }) {
348
+ async listTracks(params: { path: string }): Promise<StandardActionResponse> {
333
349
  const resp = await this.sendAction('sequence_list_tracks', { path: params.path });
334
350
  if (!resp.success && this.isUnknownActionResponse(resp)) {
335
351
  return { success: false, error: 'UNKNOWN_PLUGIN_ACTION', message: 'Automation plugin does not implement sequence_list_tracks' } as const;
@@ -348,7 +364,7 @@ export class SequenceTools extends BaseTool implements ISequenceTools {
348
364
  /**
349
365
  * Set playback work range
350
366
  */
351
- async setWorkRange(params: { path?: string; start: number; end: number }) {
367
+ async setWorkRange(params: { path?: string; start: number; end: number }): Promise<StandardActionResponse> {
352
368
  const resp = await this.sendAction('sequence_set_work_range', { path: params.path, start: params.start, end: params.end });
353
369
  if (!resp.success && this.isUnknownActionResponse(resp)) {
354
370
  return { success: false, error: 'UNKNOWN_PLUGIN_ACTION', message: 'Automation plugin does not implement sequence_set_work_range' } as const;
package/src/tools/ui.ts CHANGED
@@ -123,7 +123,6 @@ export class UITools {
123
123
  async setWidgetText(_params: {
124
124
  key: string; // The widget name to find
125
125
  value: string; // The text to set
126
- componentName?: string; // Legacy/Unused in new impl
127
126
  }) {
128
127
  if (!this.automationBridge) {
129
128
  throw new Error('Automation bridge required for setting widget text');
@@ -149,7 +148,6 @@ export class UITools {
149
148
  async setWidgetImage(_params: {
150
149
  key: string;
151
150
  texturePath: string;
152
- componentName?: string; // Unused
153
151
  }) {
154
152
  if (!this.automationBridge) {
155
153
  throw new Error('Automation bridge required for setting widget images');
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Common type definitions for automation bridge responses
3
+ * Used to provide type safety for sendAutomationRequest calls
4
+ */
5
+
6
+ /**
7
+ * Base response structure from the Automation Bridge
8
+ * Most responses follow this pattern with optional additional fields
9
+ */
10
+ export interface AutomationResponse {
11
+ success: boolean;
12
+ message?: string;
13
+ error?: string | { message: string; code?: string };
14
+ result?: unknown;
15
+ // Common additional fields
16
+ warnings?: string[];
17
+ details?: unknown;
18
+ data?: unknown;
19
+ [key: string]: unknown;
20
+ }
21
+
22
+ /**
23
+ * Level-related response fields
24
+ */
25
+ export interface LevelResponse extends AutomationResponse {
26
+ levelPath?: string;
27
+ level?: string;
28
+ path?: string;
29
+ packagePath?: string;
30
+ objectPath?: string;
31
+ currentMap?: string;
32
+ currentMapPath?: string;
33
+ currentWorldLevels?: unknown[];
34
+ allMaps?: unknown[];
35
+ partitioned?: boolean;
36
+ streaming?: boolean;
37
+ loaded?: boolean;
38
+ visible?: boolean;
39
+ skipped?: boolean;
40
+ reason?: string;
41
+ }
42
+
43
+ /**
44
+ * Actor-related response fields
45
+ */
46
+ export interface ActorResponse extends AutomationResponse {
47
+ actorName?: string;
48
+ actorLabel?: string;
49
+ actorPath?: string;
50
+ actors?: unknown[];
51
+ components?: unknown[];
52
+ location?: { x: number; y: number; z: number };
53
+ rotation?: { pitch: number; yaw: number; roll: number };
54
+ scale?: { x: number; y: number; z: number };
55
+ transform?: unknown;
56
+ tags?: string[];
57
+ properties?: Record<string, unknown>;
58
+ deleted?: boolean;
59
+ deletedCount?: number;
60
+ }
61
+
62
+ /**
63
+ * Asset-related response fields
64
+ */
65
+ export interface AssetResponse extends AutomationResponse {
66
+ assetPath?: string;
67
+ asset?: string;
68
+ assets?: unknown[];
69
+ source?: string;
70
+ saved?: boolean;
71
+ metadata?: Record<string, unknown>;
72
+ tags?: string[];
73
+ graph?: Record<string, unknown[]>;
74
+ }
75
+
76
+ /**
77
+ * Editor-related response fields
78
+ */
79
+ export interface EditorResponse extends AutomationResponse {
80
+ viewMode?: string;
81
+ fov?: number;
82
+ location?: { x: number; y: number; z: number };
83
+ rotation?: { pitch: number; yaw: number; roll: number };
84
+ cameraSettings?: unknown;
85
+ camera?: { location?: unknown; rotation?: unknown };
86
+ resolution?: { width: number; height: number };
87
+ filename?: string;
88
+ filePath?: string;
89
+ isPlaying?: boolean;
90
+ isPaused?: boolean;
91
+ isInPIE?: boolean;
92
+ playSessionId?: string;
93
+ bookmarkName?: string;
94
+ bookmarks?: unknown[];
95
+ realtime?: boolean;
96
+ }
97
+
98
+ /**
99
+ * Sequence/Animation-related response fields
100
+ */
101
+ export interface SequenceResponse extends AutomationResponse {
102
+ sequencePath?: string;
103
+ sequence?: string;
104
+ bindingId?: string;
105
+ trackName?: string;
106
+ keyframe?: unknown;
107
+ frameNumber?: number;
108
+ length?: number;
109
+ playbackPosition?: number;
110
+ requestId?: string;
111
+ }
112
+
113
+ /**
114
+ * Console command response
115
+ */
116
+ export interface ConsoleResponse extends AutomationResponse {
117
+ output?: string;
118
+ command?: string;
119
+ }