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
@@ -22,7 +22,7 @@ export declare class ActorTools extends BaseTool implements IActorTools {
22
22
  delete(params: {
23
23
  actorName?: string;
24
24
  actorNames?: string[];
25
- }): Promise<any>;
25
+ }): Promise<StandardActionResponse<any>>;
26
26
  applyForce(params: {
27
27
  actorName: string;
28
28
  force: {
@@ -30,7 +30,7 @@ export declare class ActorTools extends BaseTool implements IActorTools {
30
30
  y: number;
31
31
  z: number;
32
32
  };
33
- }): Promise<any>;
33
+ }): Promise<StandardActionResponse<any>>;
34
34
  private resolveActorClass;
35
35
  spawnBlueprint(params: {
36
36
  blueprintPath: string;
@@ -45,7 +45,7 @@ export declare class ActorTools extends BaseTool implements IActorTools {
45
45
  yaw: number;
46
46
  roll: number;
47
47
  };
48
- }): Promise<any>;
48
+ }): Promise<StandardActionResponse<any>>;
49
49
  setTransform(params: {
50
50
  actorName: string;
51
51
  location?: {
@@ -63,26 +63,48 @@ export declare class ActorTools extends BaseTool implements IActorTools {
63
63
  y: number;
64
64
  z: number;
65
65
  };
66
- }): Promise<any>;
67
- getTransform(actorName: string): Promise<any>;
66
+ }): Promise<StandardActionResponse<any>>;
67
+ getTransform(actorName: string): Promise<{
68
+ success: boolean;
69
+ error: string | {
70
+ [key: string]: unknown;
71
+ code?: string;
72
+ message: string;
73
+ };
74
+ message?: undefined;
75
+ location?: undefined;
76
+ rotation?: undefined;
77
+ scale?: undefined;
78
+ } | {
79
+ success: boolean;
80
+ message: string;
81
+ location: any;
82
+ rotation: any;
83
+ scale: any;
84
+ error?: undefined;
85
+ }>;
68
86
  setVisibility(params: {
69
87
  actorName: string;
70
88
  visible: boolean;
71
- }): Promise<any>;
89
+ }): Promise<StandardActionResponse<any>>;
72
90
  addComponent(params: {
73
91
  actorName: string;
74
92
  componentType: string;
75
93
  componentName?: string;
76
94
  properties?: Record<string, unknown>;
77
- }): Promise<any>;
95
+ }): Promise<StandardActionResponse<any>>;
78
96
  setComponentProperties(params: {
79
97
  actorName: string;
80
98
  componentName: string;
81
99
  properties: Record<string, unknown>;
82
- }): Promise<any>;
100
+ }): Promise<StandardActionResponse<any>>;
83
101
  getComponents(actorName: string): Promise<{
84
102
  success: boolean;
85
- error: any;
103
+ error: string | {
104
+ [key: string]: unknown;
105
+ code?: string;
106
+ message: string;
107
+ };
86
108
  message?: undefined;
87
109
  components?: undefined;
88
110
  count?: undefined;
@@ -101,45 +123,49 @@ export declare class ActorTools extends BaseTool implements IActorTools {
101
123
  y: number;
102
124
  z: number;
103
125
  };
104
- }): Promise<any>;
126
+ }): Promise<StandardActionResponse<any>>;
105
127
  addTag(params: {
106
128
  actorName: string;
107
129
  tag: string;
108
- }): Promise<any>;
130
+ }): Promise<StandardActionResponse<any>>;
109
131
  removeTag(params: {
110
132
  actorName: string;
111
133
  tag: string;
112
- }): Promise<any>;
134
+ }): Promise<StandardActionResponse<any>>;
113
135
  findByTag(params: {
114
136
  tag: string;
115
137
  matchType?: string;
116
- }): Promise<any>;
117
- findByName(name: string): Promise<any>;
118
- detach(actorName: string): Promise<any>;
138
+ }): Promise<StandardActionResponse<any>>;
139
+ findByName(name: string): Promise<StandardActionResponse<any>>;
140
+ detach(actorName: string): Promise<StandardActionResponse<any>>;
119
141
  attach(params: {
120
142
  childActor: string;
121
143
  parentActor: string;
122
- }): Promise<any>;
123
- deleteByTag(tag: string): Promise<any>;
144
+ }): Promise<StandardActionResponse<any>>;
145
+ deleteByTag(tag: string): Promise<StandardActionResponse<any>>;
124
146
  setBlueprintVariables(params: {
125
147
  actorName: string;
126
148
  variables: Record<string, unknown>;
127
- }): Promise<any>;
149
+ }): Promise<StandardActionResponse<any>>;
128
150
  createSnapshot(params: {
129
151
  actorName: string;
130
152
  snapshotName: string;
131
- }): Promise<any>;
153
+ }): Promise<StandardActionResponse<any>>;
132
154
  restoreSnapshot(params: {
133
155
  actorName: string;
134
156
  snapshotName: string;
135
- }): Promise<any>;
157
+ }): Promise<StandardActionResponse<any>>;
136
158
  exportActor(params: {
137
159
  actorName: string;
138
160
  destinationPath?: string;
139
- }): Promise<any>;
161
+ }): Promise<StandardActionResponse<any>>;
140
162
  getBoundingBox(actorName: string): Promise<{
141
163
  success: boolean;
142
- error: any;
164
+ error: string | {
165
+ [key: string]: unknown;
166
+ code?: string;
167
+ message: string;
168
+ };
143
169
  message?: undefined;
144
170
  boundingBox?: undefined;
145
171
  } | {
@@ -150,7 +176,11 @@ export declare class ActorTools extends BaseTool implements IActorTools {
150
176
  }>;
151
177
  getMetadata(actorName: string): Promise<{
152
178
  success: boolean;
153
- error: any;
179
+ error: string | {
180
+ [key: string]: unknown;
181
+ code?: string;
182
+ message: string;
183
+ };
154
184
  message?: undefined;
155
185
  metadata?: undefined;
156
186
  } | {
@@ -163,7 +193,11 @@ export declare class ActorTools extends BaseTool implements IActorTools {
163
193
  filter?: string;
164
194
  }): Promise<{
165
195
  success: boolean;
166
- error: any;
196
+ error: string | {
197
+ [key: string]: unknown;
198
+ code?: string;
199
+ message: string;
200
+ };
167
201
  message?: undefined;
168
202
  actors?: undefined;
169
203
  count?: undefined;
@@ -1,5 +1,6 @@
1
1
  import { ensureRotation, ensureVector3 } from '../utils/validation.js';
2
2
  import { BaseTool } from './base-tool.js';
3
+ import { wasmIntegration } from '../wasm/index.js';
3
4
  export class ActorTools extends BaseTool {
4
5
  constructor(bridge) {
5
6
  super(bridge);
@@ -38,7 +39,10 @@ export class ActorTools extends BaseTool {
38
39
  meshPath: params.meshPath
39
40
  }, timeoutMs ? { timeoutMs } : undefined);
40
41
  if (!response || !response.success) {
41
- throw new Error(response?.error || response?.message || 'Failed to spawn actor');
42
+ const error = response?.error;
43
+ const errorObj = typeof error === 'object' && error !== null ? error : null;
44
+ const errorMsg = typeof error === 'string' ? error : errorObj?.message || response?.message || 'Failed to spawn actor';
45
+ throw new Error(errorMsg);
42
46
  }
43
47
  const data = response.data || {};
44
48
  const result = {
@@ -223,10 +227,19 @@ export class ActorTools extends BaseTool {
223
227
  if (typeof actorName !== 'string' || actorName.trim().length === 0) {
224
228
  throw new Error('Invalid actorName');
225
229
  }
226
- return this.sendRequest('get_transform', { actorName }, 'control_actor')
227
- .then(response => {
228
- return response;
229
- });
230
+ const response = await this.sendRequest('get_transform', { actorName }, 'control_actor');
231
+ if (!response.success) {
232
+ return { success: false, error: response.error || `Failed to get transform for actor ${actorName}` };
233
+ }
234
+ const rawData = response.data ?? response.result ?? response;
235
+ const data = rawData?.data ?? rawData;
236
+ return {
237
+ success: true,
238
+ message: 'Transform retrieved',
239
+ location: data.location ?? data.Location,
240
+ rotation: data.rotation ?? data.Rotation,
241
+ scale: data.scale ?? data.Scale
242
+ };
230
243
  }
231
244
  async setVisibility(params) {
232
245
  const actorName = typeof params.actorName === 'string' ? params.actorName.trim() : '';
@@ -292,7 +305,10 @@ export class ActorTools extends BaseTool {
292
305
  }
293
306
  if (params.offset) {
294
307
  const offs = ensureVector3(params.offset, 'duplicate offset');
295
- payload.offset = { x: offs[0], y: offs[1], z: offs[2] };
308
+ const origin = [0, 0, 0];
309
+ const calculatedOffset = wasmIntegration.vectorAdd(origin, offs);
310
+ console.error('[WASM] Using vectorAdd for duplicate offset calculation');
311
+ payload.offset = { x: calculatedOffset[0], y: calculatedOffset[1], z: calculatedOffset[2] };
296
312
  }
297
313
  return this.sendRequest('duplicate', payload, 'control_actor');
298
314
  }
@@ -1,5 +1,5 @@
1
1
  import { BaseTool } from './base-tool.js';
2
- import { IAssetTools } from '../types/tool-interfaces.js';
2
+ import { IAssetTools, StandardActionResponse, SourceControlState } from '../types/tool-interfaces.js';
3
3
  export declare class AssetTools extends BaseTool implements IAssetTools {
4
4
  private normalizeAssetPath;
5
5
  importAsset(params: {
@@ -7,124 +7,72 @@ export declare class AssetTools extends BaseTool implements IAssetTools {
7
7
  destinationPath: string;
8
8
  overwrite?: boolean;
9
9
  save?: boolean;
10
- }): Promise<any>;
10
+ }): Promise<StandardActionResponse>;
11
11
  duplicateAsset(params: {
12
12
  sourcePath: string;
13
13
  destinationPath: string;
14
14
  overwrite?: boolean;
15
- }): Promise<any>;
15
+ }): Promise<StandardActionResponse>;
16
16
  renameAsset(params: {
17
17
  sourcePath: string;
18
18
  destinationPath: string;
19
- }): Promise<any>;
19
+ }): Promise<StandardActionResponse>;
20
20
  moveAsset(params: {
21
21
  sourcePath: string;
22
22
  destinationPath: string;
23
- }): Promise<any>;
23
+ }): Promise<StandardActionResponse>;
24
24
  findByTag(params: {
25
25
  tag: string;
26
26
  value?: string;
27
- }): Promise<any>;
27
+ }): Promise<StandardActionResponse>;
28
28
  deleteAssets(params: {
29
29
  paths: string[];
30
30
  fixupRedirectors?: boolean;
31
31
  timeoutMs?: number;
32
- }): Promise<any>;
32
+ }): Promise<StandardActionResponse>;
33
33
  searchAssets(params: {
34
34
  classNames?: string[];
35
35
  packagePaths?: string[];
36
36
  recursivePaths?: boolean;
37
37
  recursiveClasses?: boolean;
38
38
  limit?: number;
39
- }): Promise<{
40
- success: boolean;
41
- error: any;
42
- message?: undefined;
43
- assets?: undefined;
44
- count?: undefined;
45
- } | {
46
- success: boolean;
47
- message: string;
48
- assets: any[];
49
- count: number;
50
- error?: undefined;
51
- }>;
52
- saveAsset(assetPath: string): Promise<any>;
53
- createFolder(folderPath: string): Promise<any>;
39
+ }): Promise<StandardActionResponse>;
40
+ saveAsset(assetPath: string): Promise<StandardActionResponse>;
41
+ createFolder(folderPath: string): Promise<StandardActionResponse>;
54
42
  getDependencies(params: {
55
43
  assetPath: string;
56
44
  recursive?: boolean;
57
- }): Promise<any>;
45
+ }): Promise<StandardActionResponse>;
58
46
  getSourceControlState(params: {
59
47
  assetPath: string;
60
- }): Promise<any>;
48
+ }): Promise<SourceControlState | StandardActionResponse>;
61
49
  getMetadata(params: {
62
50
  assetPath: string;
63
- }): Promise<{
64
- success: boolean;
65
- message: string;
66
- }>;
51
+ }): Promise<StandardActionResponse>;
67
52
  analyzeGraph(params: {
68
53
  assetPath: string;
69
54
  maxDepth?: number;
70
- }): Promise<{
71
- success: boolean;
72
- error: any;
73
- message?: undefined;
74
- analysis?: undefined;
75
- } | {
76
- success: boolean;
77
- message: string;
78
- analysis: {
79
- asset: any;
80
- dependencies: any[];
81
- totalDependencyCount: any;
82
- requestedMaxDepth: number;
83
- maxDepthUsed: number;
84
- circularDependencies: string[][];
85
- topologicalOrder: string[];
86
- stats: {
87
- nodeCount: number;
88
- leafCount: number;
89
- };
90
- };
91
- error?: undefined;
92
- }>;
55
+ }): Promise<StandardActionResponse>;
93
56
  createThumbnail(params: {
94
57
  assetPath: string;
95
58
  width?: number;
96
59
  height?: number;
97
- }): Promise<any>;
60
+ }): Promise<StandardActionResponse>;
98
61
  setTags(params: {
99
62
  assetPath: string;
100
63
  tags: string[];
101
- }): Promise<any>;
64
+ }): Promise<StandardActionResponse>;
102
65
  generateReport(params: {
103
66
  directory: string;
104
67
  reportType?: string;
105
68
  outputPath?: string;
106
- }): Promise<any>;
69
+ }): Promise<StandardActionResponse>;
107
70
  validate(params: {
108
71
  assetPath: string;
109
- }): Promise<any>;
72
+ }): Promise<StandardActionResponse>;
110
73
  generateLODs(params: {
111
74
  assetPath: string;
112
75
  lodCount: number;
113
- }): Promise<{
114
- success: boolean;
115
- error: string;
116
- details?: undefined;
117
- } | {
118
- success: boolean;
119
- error: any;
120
- details: any;
121
- } | {
122
- success: boolean;
123
- message: any;
124
- assetPath: string;
125
- lodCount: number;
126
- error?: undefined;
127
- details?: undefined;
128
- }>;
76
+ }): Promise<StandardActionResponse>;
129
77
  }
130
78
  //# sourceMappingURL=assets.d.ts.map
@@ -1,5 +1,9 @@
1
1
  import { BaseTool } from './base-tool.js';
2
2
  import { wasmIntegration } from '../wasm/index.js';
3
+ import { Logger } from '../utils/logger.js';
4
+ import { sanitizePath } from '../utils/path-security.js';
5
+ import { DEFAULT_ASSET_OP_TIMEOUT_MS, EXTENDED_ASSET_OP_TIMEOUT_MS, LONG_RUNNING_OP_TIMEOUT_MS } from '../constants.js';
6
+ const log = new Logger('AssetTools');
3
7
  export class AssetTools extends BaseTool {
4
8
  normalizeAssetPath(path) {
5
9
  if (!path)
@@ -15,13 +19,14 @@ export class AssetTools extends BaseTool {
15
19
  else
16
20
  normalized = '/Game/' + normalized;
17
21
  }
18
- return normalized.replace(/\/+/g, '/');
22
+ normalized = normalized.replace(/\/+/g, '/');
23
+ return sanitizePath(normalized);
19
24
  }
20
25
  async importAsset(params) {
21
26
  const res = await this.sendRequest('manage_asset', {
22
27
  ...params,
23
28
  subAction: 'import'
24
- }, 'manage_asset', { timeoutMs: 120000 });
29
+ }, 'manage_asset', { timeoutMs: EXTENDED_ASSET_OP_TIMEOUT_MS });
25
30
  if (res && res.success) {
26
31
  return { ...res, asset: this.normalizeAssetPath(params.destinationPath), source: params.sourcePath };
27
32
  }
@@ -35,7 +40,7 @@ export class AssetTools extends BaseTool {
35
40
  destinationPath,
36
41
  overwrite: params.overwrite ?? false,
37
42
  subAction: 'duplicate'
38
- }, 'manage_asset', { timeoutMs: 60000 });
43
+ }, 'manage_asset', { timeoutMs: DEFAULT_ASSET_OP_TIMEOUT_MS });
39
44
  if (res && res.success) {
40
45
  return { ...res, asset: destinationPath, source: sourcePath };
41
46
  }
@@ -48,7 +53,7 @@ export class AssetTools extends BaseTool {
48
53
  sourcePath,
49
54
  destinationPath,
50
55
  subAction: 'rename'
51
- }, 'manage_asset', { timeoutMs: 60000 });
56
+ }, 'manage_asset', { timeoutMs: DEFAULT_ASSET_OP_TIMEOUT_MS });
52
57
  if (res && res.success) {
53
58
  return { ...res, asset: destinationPath, oldName: sourcePath };
54
59
  }
@@ -61,7 +66,7 @@ export class AssetTools extends BaseTool {
61
66
  sourcePath,
62
67
  destinationPath,
63
68
  subAction: 'move'
64
- }, 'manage_asset', { timeoutMs: 60000 });
69
+ }, 'manage_asset', { timeoutMs: DEFAULT_ASSET_OP_TIMEOUT_MS });
65
70
  if (res && res.success) {
66
71
  return { ...res, asset: destinationPath, from: sourcePath };
67
72
  }
@@ -71,7 +76,7 @@ export class AssetTools extends BaseTool {
71
76
  return this.sendRequest('asset_query', {
72
77
  ...params,
73
78
  subAction: 'find_by_tag'
74
- }, 'asset_query', { timeoutMs: 60000 });
79
+ }, 'asset_query', { timeoutMs: DEFAULT_ASSET_OP_TIMEOUT_MS });
75
80
  }
76
81
  async deleteAssets(params) {
77
82
  const assetPaths = (Array.isArray(params.paths) ? params.paths : [])
@@ -80,7 +85,7 @@ export class AssetTools extends BaseTool {
80
85
  assetPaths,
81
86
  fixupRedirectors: params.fixupRedirectors,
82
87
  subAction: 'delete'
83
- }, 'manage_asset', { timeoutMs: params.timeoutMs || 120000 });
88
+ }, 'manage_asset', { timeoutMs: params.timeoutMs || EXTENDED_ASSET_OP_TIMEOUT_MS });
84
89
  }
85
90
  async searchAssets(params) {
86
91
  const packagePaths = params.packagePaths
@@ -90,10 +95,10 @@ export class AssetTools extends BaseTool {
90
95
  ...params,
91
96
  packagePaths,
92
97
  subAction: 'search_assets'
93
- }, 'asset_query', { timeoutMs: 60000 });
98
+ }, 'asset_query', { timeoutMs: DEFAULT_ASSET_OP_TIMEOUT_MS });
94
99
  if (!response.success) {
95
- const errorMsg = response.error || `Failed to search assets. Raw response: ${JSON.stringify(response)}`;
96
- return { success: false, error: errorMsg };
100
+ const errorMsg = typeof response.error === 'string' ? response.error : JSON.stringify(response.error);
101
+ return { success: false, error: errorMsg || 'Failed to search assets' };
97
102
  }
98
103
  const assetsRaw = response.assets || response.data || response.result;
99
104
  const assets = Array.isArray(assetsRaw) ? assetsRaw : [];
@@ -110,7 +115,7 @@ export class AssetTools extends BaseTool {
110
115
  const bridge = this.getAutomationBridge();
111
116
  if (bridge && typeof bridge.sendAutomationRequest === 'function') {
112
117
  try {
113
- const response = await bridge.sendAutomationRequest('manage_asset', { assetPath: normalizedPath, subAction: 'save_asset' }, { timeoutMs: 60000 });
118
+ const response = await bridge.sendAutomationRequest('manage_asset', { assetPath: normalizedPath, subAction: 'save_asset' }, { timeoutMs: DEFAULT_ASSET_OP_TIMEOUT_MS });
114
119
  if (response && response.success !== false) {
115
120
  return {
116
121
  success: true,
@@ -120,7 +125,8 @@ export class AssetTools extends BaseTool {
120
125
  };
121
126
  }
122
127
  }
123
- catch (_err) {
128
+ catch (primaryError) {
129
+ log.debug('saveAsset primary method failed, trying fallback', primaryError);
124
130
  }
125
131
  }
126
132
  const res = await this.bridge.executeEditorFunction('SAVE_ASSET', { path: normalizedPath });
@@ -131,7 +137,7 @@ export class AssetTools extends BaseTool {
131
137
  return { success: false, error: res?.error ?? 'Failed to save asset' };
132
138
  }
133
139
  catch (err) {
134
- return { success: false, error: `Failed to save asset: ${err}` };
140
+ return { success: false, error: `Failed to save asset: ${err} ` };
135
141
  }
136
142
  }
137
143
  async createFolder(folderPath) {
@@ -139,7 +145,7 @@ export class AssetTools extends BaseTool {
139
145
  return this.sendRequest('manage_asset', {
140
146
  path,
141
147
  subAction: 'create_folder'
142
- }, 'manage_asset', { timeoutMs: 60000 });
148
+ }, 'manage_asset', { timeoutMs: DEFAULT_ASSET_OP_TIMEOUT_MS });
143
149
  }
144
150
  async getDependencies(params) {
145
151
  return this.sendRequest('manage_asset', {
@@ -176,7 +182,7 @@ export class AssetTools extends BaseTool {
176
182
  assetPath,
177
183
  maxDepth,
178
184
  subAction: 'get_asset_graph'
179
- }, 'manage_asset', { timeoutMs: 60000 });
185
+ }, 'manage_asset', { timeoutMs: DEFAULT_ASSET_OP_TIMEOUT_MS });
180
186
  if (!response.success || !response.graph) {
181
187
  return { success: false, error: response.error || 'Failed to retrieve asset graph from engine' };
182
188
  }
@@ -216,7 +222,7 @@ export class AssetTools extends BaseTool {
216
222
  };
217
223
  }
218
224
  catch (e) {
219
- return { success: false, error: `Analysis failed: ${e.message}` };
225
+ return { success: false, error: `Analysis failed: ${e instanceof Error ? e.message : String(e)} ` };
220
226
  }
221
227
  }
222
228
  async createThumbnail(params) {
@@ -224,28 +230,28 @@ export class AssetTools extends BaseTool {
224
230
  ...params,
225
231
  assetPath: this.normalizeAssetPath(params.assetPath),
226
232
  subAction: 'generate_thumbnail'
227
- }, 'manage_asset', { timeoutMs: 60000 });
233
+ }, 'manage_asset', { timeoutMs: DEFAULT_ASSET_OP_TIMEOUT_MS });
228
234
  }
229
235
  async setTags(params) {
230
236
  return this.sendRequest('manage_asset', {
231
237
  ...params,
232
238
  assetPath: this.normalizeAssetPath(params.assetPath),
233
239
  subAction: 'set_tags'
234
- }, 'manage_asset', { timeoutMs: 60000 });
240
+ }, 'manage_asset', { timeoutMs: DEFAULT_ASSET_OP_TIMEOUT_MS });
235
241
  }
236
242
  async generateReport(params) {
237
243
  return this.sendRequest('manage_asset', {
238
244
  ...params,
239
245
  directory: this.normalizeAssetPath(params.directory),
240
246
  subAction: 'generate_report'
241
- }, 'manage_asset', { timeoutMs: 300000 });
247
+ }, 'manage_asset', { timeoutMs: LONG_RUNNING_OP_TIMEOUT_MS });
242
248
  }
243
249
  async validate(params) {
244
250
  return this.sendRequest('manage_asset', {
245
251
  ...params,
246
252
  assetPath: this.normalizeAssetPath(params.assetPath),
247
253
  subAction: 'validate'
248
- }, 'manage_asset', { timeoutMs: 300000 });
254
+ }, 'manage_asset', { timeoutMs: LONG_RUNNING_OP_TIMEOUT_MS });
249
255
  }
250
256
  async generateLODs(params) {
251
257
  const assetPath = this.normalizeAssetPath(String(params.assetPath ?? '').trim());
@@ -263,7 +269,7 @@ export class AssetTools extends BaseTool {
263
269
  assetPaths: [assetPath],
264
270
  numLODs: lodCount,
265
271
  subAction: 'generate_lods'
266
- }, { timeoutMs: 120000 });
272
+ }, { timeoutMs: EXTENDED_ASSET_OP_TIMEOUT_MS });
267
273
  if (!response || response.success === false) {
268
274
  return {
269
275
  success: false,
@@ -283,7 +289,7 @@ export class AssetTools extends BaseTool {
283
289
  catch (error) {
284
290
  return {
285
291
  success: false,
286
- error: `Failed to generate LODs: ${error instanceof Error ? error.message : String(error)}`
292
+ error: `Failed to generate LODs: ${error instanceof Error ? error.message : String(error)} `
287
293
  };
288
294
  }
289
295
  }
@@ -5,13 +5,13 @@ export declare abstract class BaseTool implements IBaseTool {
5
5
  protected bridge: UnrealBridge;
6
6
  constructor(bridge: UnrealBridge);
7
7
  getAutomationBridge(): AutomationBridge;
8
- protected sendRequest(action: string, params: Record<string, unknown>, toolName?: string, options?: {
8
+ protected sendRequest<T = unknown>(action: string, params: Record<string, unknown>, toolName?: string, options?: {
9
9
  timeoutMs?: number;
10
- }): Promise<any>;
11
- protected sendAutomationRequest(action: string, params?: Record<string, unknown>, options?: {
10
+ }): Promise<T>;
11
+ protected sendAutomationRequest<T = unknown>(action: string, params?: Record<string, unknown>, options?: {
12
12
  timeoutMs?: number;
13
13
  waitForEvent?: boolean;
14
14
  waitForEventTimeoutMs?: number;
15
- }): Promise<any>;
15
+ }): Promise<T>;
16
16
  }
17
17
  //# sourceMappingURL=base-tool.d.ts.map
@@ -33,7 +33,7 @@ export class BaseTool {
33
33
  }
34
34
  throw new Error(errorMessage);
35
35
  }
36
- return response.result ?? response;
36
+ return (response.result ?? response);
37
37
  }
38
38
  async sendAutomationRequest(action, params = {}, options) {
39
39
  const automation = this.getAutomationBridge();