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.
- package/.env.example +1 -1
- package/.github/release-drafter-config.yml +51 -0
- package/.github/workflows/greetings.yml +5 -1
- package/.github/workflows/labeler.yml +2 -1
- package/.github/workflows/publish-mcp.yml +2 -4
- package/.github/workflows/release-drafter.yml +3 -2
- package/.github/workflows/release.yml +3 -3
- package/CHANGELOG.md +109 -0
- package/CONTRIBUTING.md +1 -1
- package/GEMINI.md +115 -0
- package/Public/Plugin_setup_guide.mp4 +0 -0
- package/README.md +166 -200
- package/dist/automation/bridge.d.ts +1 -2
- package/dist/automation/bridge.js +24 -23
- package/dist/automation/connection-manager.d.ts +1 -0
- package/dist/automation/connection-manager.js +10 -0
- package/dist/automation/message-handler.js +5 -4
- package/dist/automation/request-tracker.d.ts +4 -0
- package/dist/automation/request-tracker.js +11 -3
- package/dist/config.d.ts +0 -1
- package/dist/config.js +0 -1
- package/dist/constants.d.ts +4 -0
- package/dist/constants.js +4 -0
- package/dist/graphql/loaders.d.ts +64 -0
- package/dist/graphql/loaders.js +117 -0
- package/dist/graphql/resolvers.d.ts +3 -3
- package/dist/graphql/resolvers.js +33 -30
- package/dist/graphql/server.js +3 -1
- package/dist/graphql/types.d.ts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +13 -2
- package/dist/server-setup.d.ts +0 -1
- package/dist/server-setup.js +0 -40
- package/dist/tools/actors.d.ts +58 -24
- package/dist/tools/actors.js +22 -6
- package/dist/tools/assets.d.ts +19 -71
- package/dist/tools/assets.js +28 -22
- package/dist/tools/base-tool.d.ts +4 -4
- package/dist/tools/base-tool.js +1 -1
- package/dist/tools/blueprint.d.ts +45 -61
- package/dist/tools/blueprint.js +43 -14
- package/dist/tools/consolidated-tool-definitions.js +2 -1
- package/dist/tools/consolidated-tool-handlers.js +96 -110
- package/dist/tools/dynamic-handler-registry.d.ts +11 -9
- package/dist/tools/dynamic-handler-registry.js +17 -95
- package/dist/tools/editor.d.ts +19 -193
- package/dist/tools/editor.js +11 -2
- package/dist/tools/environment.d.ts +8 -14
- package/dist/tools/foliage.d.ts +18 -143
- package/dist/tools/foliage.js +4 -2
- package/dist/tools/handlers/actor-handlers.d.ts +1 -1
- package/dist/tools/handlers/actor-handlers.js +14 -13
- package/dist/tools/handlers/asset-handlers.js +454 -454
- package/dist/tools/handlers/sequence-handlers.d.ts +1 -1
- package/dist/tools/handlers/sequence-handlers.js +24 -13
- package/dist/tools/introspection.d.ts +1 -1
- package/dist/tools/introspection.js +1 -1
- package/dist/tools/landscape.d.ts +16 -116
- package/dist/tools/landscape.js +7 -3
- package/dist/tools/level.d.ts +22 -103
- package/dist/tools/level.js +26 -18
- package/dist/tools/lighting.d.ts +54 -7
- package/dist/tools/lighting.js +9 -5
- package/dist/tools/materials.d.ts +1 -1
- package/dist/tools/materials.js +5 -1
- package/dist/tools/niagara.js +37 -2
- package/dist/tools/performance.d.ts +0 -1
- package/dist/tools/performance.js +0 -1
- package/dist/tools/physics.js +5 -1
- package/dist/tools/sequence.d.ts +24 -24
- package/dist/tools/sequence.js +13 -0
- package/dist/tools/ui.d.ts +0 -2
- package/dist/types/automation-responses.d.ts +115 -0
- package/dist/types/automation-responses.js +2 -0
- package/dist/types/responses.d.ts +249 -0
- package/dist/types/responses.js +2 -0
- package/dist/types/tool-interfaces.d.ts +135 -135
- package/dist/types/tool-types.d.ts +2 -0
- package/dist/unreal-bridge.js +4 -4
- package/dist/utils/command-validator.js +7 -5
- package/dist/utils/error-handler.d.ts +24 -2
- package/dist/utils/error-handler.js +58 -23
- package/dist/utils/normalize.d.ts +7 -4
- package/dist/utils/normalize.js +12 -10
- package/dist/utils/path-security.d.ts +2 -0
- package/dist/utils/path-security.js +24 -0
- package/dist/utils/response-factory.d.ts +4 -4
- package/dist/utils/response-factory.js +15 -21
- package/dist/utils/response-validator.js +88 -73
- package/dist/utils/unreal-command-queue.d.ts +2 -0
- package/dist/utils/unreal-command-queue.js +8 -1
- package/docs/Migration-Guide-v0.5.0.md +1 -9
- package/docs/handler-mapping.md +4 -2
- package/docs/testing-guide.md +2 -2
- package/package.json +12 -6
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSubsystem.cpp +298 -33
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AnimationHandlers.cpp +7 -8
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintGraphHandlers.cpp +229 -319
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers.cpp +98 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EffectHandlers.cpp +24 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EnvironmentHandlers.cpp +96 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LightingHandlers.cpp +52 -5
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ProcessRequest.cpp +5 -268
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequenceHandlers.cpp +57 -2
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpConnectionManager.cpp +0 -1
- package/scripts/run-all-tests.mjs +25 -20
- package/server.json +3 -2
- package/src/automation/bridge.ts +27 -25
- package/src/automation/connection-manager.ts +18 -0
- package/src/automation/message-handler.ts +33 -8
- package/src/automation/request-tracker.ts +39 -7
- package/src/config.ts +1 -1
- package/src/constants.ts +7 -0
- package/src/graphql/loaders.ts +244 -0
- package/src/graphql/resolvers.ts +47 -49
- package/src/graphql/server.ts +3 -1
- package/src/graphql/types.ts +3 -0
- package/src/index.ts +15 -2
- package/src/resources/assets.ts +5 -4
- package/src/server/tool-registry.ts +3 -3
- package/src/server-setup.ts +3 -37
- package/src/tools/actors.ts +77 -44
- package/src/tools/animation.ts +1 -0
- package/src/tools/assets.ts +76 -65
- package/src/tools/base-tool.ts +3 -3
- package/src/tools/blueprint.ts +170 -104
- package/src/tools/consolidated-tool-definitions.ts +2 -1
- package/src/tools/consolidated-tool-handlers.ts +129 -150
- package/src/tools/dynamic-handler-registry.ts +22 -140
- package/src/tools/editor.ts +43 -29
- package/src/tools/environment.ts +21 -27
- package/src/tools/foliage.ts +28 -25
- package/src/tools/handlers/actor-handlers.ts +16 -17
- package/src/tools/handlers/asset-handlers.ts +484 -484
- package/src/tools/handlers/sequence-handlers.ts +85 -62
- package/src/tools/introspection.ts +7 -7
- package/src/tools/landscape.ts +34 -28
- package/src/tools/level.ts +100 -80
- package/src/tools/lighting.ts +25 -20
- package/src/tools/materials.ts +9 -3
- package/src/tools/niagara.ts +44 -2
- package/src/tools/performance.ts +1 -2
- package/src/tools/physics.ts +7 -1
- package/src/tools/sequence.ts +42 -26
- package/src/tools/ui.ts +1 -3
- package/src/types/automation-responses.ts +119 -0
- package/src/types/responses.ts +355 -0
- package/src/types/tool-interfaces.ts +135 -135
- package/src/types/tool-types.ts +4 -0
- package/src/unreal-bridge.ts +71 -26
- package/src/utils/command-validator.ts +47 -5
- package/src/utils/error-handler.ts +128 -45
- package/src/utils/normalize.test.ts +162 -0
- package/src/utils/normalize.ts +38 -16
- package/src/utils/path-security.ts +43 -0
- package/src/utils/response-factory.ts +29 -24
- package/src/utils/response-validator.ts +103 -87
- package/src/utils/safe-json.test.ts +90 -0
- package/src/utils/unreal-command-queue.ts +13 -1
- package/src/utils/validation.test.ts +184 -0
- package/tests/test-animation.mjs +358 -33
- package/tests/test-asset-graph.mjs +311 -0
- package/tests/test-audio.mjs +314 -116
- package/tests/test-behavior-tree.mjs +327 -144
- package/tests/test-blueprint-graph.mjs +343 -12
- package/tests/test-control-editor.mjs +85 -53
- package/tests/test-graphql.mjs +58 -8
- package/tests/test-input.mjs +349 -0
- package/tests/test-inspect.mjs +291 -61
- package/tests/test-landscape.mjs +304 -48
- package/tests/test-lighting.mjs +428 -0
- package/tests/test-manage-level.mjs +70 -51
- package/tests/test-performance.mjs +539 -0
- package/tests/test-sequence.mjs +82 -46
- package/tests/test-system.mjs +72 -33
- package/tests/test-wasm.mjs +98 -8
- package/vitest.config.ts +35 -0
- package/.github/release-drafter.yml +0 -148
- package/dist/prompts/index.d.ts +0 -21
- package/dist/prompts/index.js +0 -217
- package/dist/tools/blueprint/helpers.d.ts +0 -29
- package/dist/tools/blueprint/helpers.js +0 -182
- package/src/prompts/index.ts +0 -249
- package/src/tools/blueprint/helpers.ts +0 -189
- package/tests/test-blueprint-events.mjs +0 -35
- package/tests/test-extra-tools.mjs +0 -38
- package/tests/test-render.mjs +0 -33
- package/tests/test-search-assets.mjs +0 -66
|
@@ -1,496 +1,496 @@
|
|
|
1
1
|
import { cleanObject } from '../../utils/safe-json.js';
|
|
2
2
|
import { executeAutomationRequest } from './common-handlers.js';
|
|
3
3
|
import { normalizeArgs } from './argument-helper.js';
|
|
4
|
+
import { ResponseFactory } from '../../utils/response-factory.js';
|
|
4
5
|
export async function handleAssetTools(action, args, tools) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
(Array.isArray(response.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
6
|
+
try {
|
|
7
|
+
switch (action) {
|
|
8
|
+
case 'list': {
|
|
9
|
+
const params = normalizeArgs(args, [
|
|
10
|
+
{ key: 'path', aliases: ['directory', 'assetPath'], default: '/Game' },
|
|
11
|
+
{ key: 'limit', default: 50 },
|
|
12
|
+
{ key: 'recursive', default: false },
|
|
13
|
+
{ key: 'depth', default: undefined }
|
|
14
|
+
]);
|
|
15
|
+
const recursive = params.recursive === true || (params.depth !== undefined && params.depth > 0);
|
|
16
|
+
const res = await executeAutomationRequest(tools, 'list', {
|
|
17
|
+
path: params.path,
|
|
18
|
+
recursive,
|
|
19
|
+
depth: params.depth
|
|
20
|
+
});
|
|
21
|
+
const response = res;
|
|
22
|
+
const assets = (Array.isArray(response.assets) ? response.assets :
|
|
23
|
+
(Array.isArray(response.result) ? response.result : (response.result?.assets || [])));
|
|
24
|
+
const folders = Array.isArray(response.folders) ? response.folders : (response.result?.folders || []);
|
|
25
|
+
const totalCount = assets.length;
|
|
26
|
+
const limitedAssets = assets.slice(0, params.limit);
|
|
27
|
+
const remaining = Math.max(0, totalCount - params.limit);
|
|
28
|
+
let message = `Found ${totalCount} assets`;
|
|
29
|
+
if (folders.length > 0) {
|
|
30
|
+
message += ` and ${folders.length} folders`;
|
|
31
|
+
}
|
|
32
|
+
message += `: ${limitedAssets.map((a) => a.path || a.package || a.name).join(', ')}`;
|
|
33
|
+
if (folders.length > 0 && limitedAssets.length < params.limit) {
|
|
34
|
+
const remainingLimit = params.limit - limitedAssets.length;
|
|
35
|
+
if (remainingLimit > 0) {
|
|
36
|
+
const limitedFolders = folders.slice(0, remainingLimit);
|
|
37
|
+
if (limitedAssets.length > 0)
|
|
38
|
+
message += ', ';
|
|
39
|
+
message += `Folders: [${limitedFolders.join(', ')}]`;
|
|
40
|
+
if (folders.length > remainingLimit)
|
|
41
|
+
message += '...';
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (remaining > 0) {
|
|
45
|
+
message += `... and ${remaining} others`;
|
|
40
46
|
}
|
|
47
|
+
return ResponseFactory.success({
|
|
48
|
+
assets: limitedAssets,
|
|
49
|
+
folders: folders,
|
|
50
|
+
totalCount: totalCount,
|
|
51
|
+
count: limitedAssets.length
|
|
52
|
+
}, message);
|
|
41
53
|
}
|
|
42
|
-
|
|
43
|
-
|
|
54
|
+
case 'create_folder': {
|
|
55
|
+
const params = normalizeArgs(args, [
|
|
56
|
+
{ key: 'path', aliases: ['directoryPath'], required: true }
|
|
57
|
+
]);
|
|
58
|
+
const res = await tools.assetTools.createFolder(params.path);
|
|
59
|
+
return ResponseFactory.success(res, 'Folder created successfully');
|
|
44
60
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
{ key: 'newName' }
|
|
80
|
-
]);
|
|
81
|
-
let destinationPath = params.destinationPath;
|
|
82
|
-
if (params.newName) {
|
|
61
|
+
case 'import': {
|
|
62
|
+
const params = normalizeArgs(args, [
|
|
63
|
+
{ key: 'sourcePath', required: true },
|
|
64
|
+
{ key: 'destinationPath', required: true },
|
|
65
|
+
{ key: 'overwrite', default: false },
|
|
66
|
+
{ key: 'save', default: true }
|
|
67
|
+
]);
|
|
68
|
+
const res = await tools.assetTools.importAsset({
|
|
69
|
+
sourcePath: params.sourcePath,
|
|
70
|
+
destinationPath: params.destinationPath,
|
|
71
|
+
overwrite: params.overwrite,
|
|
72
|
+
save: params.save
|
|
73
|
+
});
|
|
74
|
+
return ResponseFactory.success(res, 'Asset imported successfully');
|
|
75
|
+
}
|
|
76
|
+
case 'duplicate': {
|
|
77
|
+
const params = normalizeArgs(args, [
|
|
78
|
+
{ key: 'sourcePath', aliases: ['assetPath'], required: true },
|
|
79
|
+
{ key: 'destinationPath' },
|
|
80
|
+
{ key: 'newName' }
|
|
81
|
+
]);
|
|
82
|
+
let destinationPath = params.destinationPath;
|
|
83
|
+
if (params.newName) {
|
|
84
|
+
if (!destinationPath) {
|
|
85
|
+
const lastSlash = params.sourcePath.lastIndexOf('/');
|
|
86
|
+
const parentDir = lastSlash > 0 ? params.sourcePath.substring(0, lastSlash) : '/Game';
|
|
87
|
+
destinationPath = `${parentDir}/${params.newName}`;
|
|
88
|
+
}
|
|
89
|
+
else if (!destinationPath.endsWith(params.newName)) {
|
|
90
|
+
if (destinationPath.endsWith('/')) {
|
|
91
|
+
destinationPath = `${destinationPath}${params.newName}`;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
83
95
|
if (!destinationPath) {
|
|
96
|
+
throw new Error('destinationPath or newName is required for duplicate action');
|
|
97
|
+
}
|
|
98
|
+
const res = await tools.assetTools.duplicateAsset({
|
|
99
|
+
sourcePath: params.sourcePath,
|
|
100
|
+
destinationPath
|
|
101
|
+
});
|
|
102
|
+
return ResponseFactory.success(res, 'Asset duplicated successfully');
|
|
103
|
+
}
|
|
104
|
+
case 'rename': {
|
|
105
|
+
const params = normalizeArgs(args, [
|
|
106
|
+
{ key: 'sourcePath', aliases: ['assetPath'], required: true },
|
|
107
|
+
{ key: 'destinationPath' },
|
|
108
|
+
{ key: 'newName' }
|
|
109
|
+
]);
|
|
110
|
+
let destinationPath = params.destinationPath;
|
|
111
|
+
if (!destinationPath && params.newName) {
|
|
84
112
|
const lastSlash = params.sourcePath.lastIndexOf('/');
|
|
85
113
|
const parentDir = lastSlash > 0 ? params.sourcePath.substring(0, lastSlash) : '/Game';
|
|
86
114
|
destinationPath = `${parentDir}/${params.newName}`;
|
|
87
115
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
116
|
+
if (!destinationPath)
|
|
117
|
+
throw new Error('Missing destinationPath or newName');
|
|
118
|
+
const res = await tools.assetTools.renameAsset({
|
|
119
|
+
sourcePath: params.sourcePath,
|
|
120
|
+
destinationPath
|
|
121
|
+
});
|
|
122
|
+
if (res && res.success === false) {
|
|
123
|
+
const msg = (res.message || '').toLowerCase();
|
|
124
|
+
if (msg.includes('already exists') || msg.includes('exists')) {
|
|
125
|
+
return cleanObject({
|
|
126
|
+
success: false,
|
|
127
|
+
error: 'ASSET_ALREADY_EXISTS',
|
|
128
|
+
message: res.message || 'Asset already exists at destination',
|
|
129
|
+
sourcePath: params.sourcePath,
|
|
130
|
+
destinationPath
|
|
131
|
+
});
|
|
91
132
|
}
|
|
92
133
|
}
|
|
134
|
+
return cleanObject(res);
|
|
93
135
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
destinationPath
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
let destinationPath = params.destinationPath;
|
|
110
|
-
if (!destinationPath && params.newName) {
|
|
111
|
-
const lastSlash = params.sourcePath.lastIndexOf('/');
|
|
112
|
-
const parentDir = lastSlash > 0 ? params.sourcePath.substring(0, lastSlash) : '/Game';
|
|
113
|
-
destinationPath = `${parentDir}/${params.newName}`;
|
|
136
|
+
case 'move': {
|
|
137
|
+
const params = normalizeArgs(args, [
|
|
138
|
+
{ key: 'sourcePath', aliases: ['assetPath'], required: true },
|
|
139
|
+
{ key: 'destinationPath' }
|
|
140
|
+
]);
|
|
141
|
+
let destinationPath = params.destinationPath;
|
|
142
|
+
const assetName = params.sourcePath.split('/').pop();
|
|
143
|
+
if (assetName && destinationPath && !destinationPath.endsWith(assetName)) {
|
|
144
|
+
destinationPath = `${destinationPath.replace(/\/$/, '')}/${assetName}`;
|
|
145
|
+
}
|
|
146
|
+
const res = await tools.assetTools.moveAsset({
|
|
147
|
+
sourcePath: params.sourcePath,
|
|
148
|
+
destinationPath
|
|
149
|
+
});
|
|
150
|
+
return ResponseFactory.success(res, 'Asset moved successfully');
|
|
114
151
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
if (res && res.success === false) {
|
|
122
|
-
const msg = (res.message || '').toLowerCase();
|
|
123
|
-
if (msg.includes('already exists') || msg.includes('exists')) {
|
|
124
|
-
return cleanObject({
|
|
125
|
-
success: false,
|
|
126
|
-
error: 'ASSET_ALREADY_EXISTS',
|
|
127
|
-
message: res.message || 'Asset already exists at destination',
|
|
128
|
-
sourcePath: params.sourcePath,
|
|
129
|
-
destinationPath
|
|
130
|
-
});
|
|
152
|
+
case 'delete_assets':
|
|
153
|
+
case 'delete_asset':
|
|
154
|
+
case 'delete': {
|
|
155
|
+
let paths = [];
|
|
156
|
+
if (Array.isArray(args.paths)) {
|
|
157
|
+
paths = args.paths;
|
|
131
158
|
}
|
|
159
|
+
else if (Array.isArray(args.assetPaths)) {
|
|
160
|
+
paths = args.assetPaths;
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
const single = args.assetPath || args.path;
|
|
164
|
+
if (typeof single === 'string' && single.trim()) {
|
|
165
|
+
paths = [single.trim()];
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (paths.length === 0) {
|
|
169
|
+
throw new Error('No paths provided for delete action');
|
|
170
|
+
}
|
|
171
|
+
const res = await tools.assetTools.deleteAssets({ paths });
|
|
172
|
+
return ResponseFactory.success(res, 'Assets deleted successfully');
|
|
132
173
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
destinationPath = `${destinationPath.replace(/\/$/, '')}/${assetName}`;
|
|
174
|
+
case 'generate_lods': {
|
|
175
|
+
const params = normalizeArgs(args, [
|
|
176
|
+
{ key: 'assetPath', required: true },
|
|
177
|
+
{ key: 'lodCount', required: true }
|
|
178
|
+
]);
|
|
179
|
+
const res = await tools.assetTools.generateLODs({
|
|
180
|
+
assetPath: params.assetPath,
|
|
181
|
+
lodCount: params.lodCount
|
|
182
|
+
});
|
|
183
|
+
return ResponseFactory.success(res, 'LODs generated successfully');
|
|
144
184
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
185
|
+
case 'create_thumbnail': {
|
|
186
|
+
const params = normalizeArgs(args, [
|
|
187
|
+
{ key: 'assetPath', required: true },
|
|
188
|
+
{ key: 'width' },
|
|
189
|
+
{ key: 'height' }
|
|
190
|
+
]);
|
|
191
|
+
const res = await tools.assetTools.createThumbnail({
|
|
192
|
+
assetPath: params.assetPath,
|
|
193
|
+
width: params.width,
|
|
194
|
+
height: params.height
|
|
195
|
+
});
|
|
196
|
+
return ResponseFactory.success(res, 'Thumbnail created successfully');
|
|
157
197
|
}
|
|
158
|
-
|
|
159
|
-
|
|
198
|
+
case 'set_tags': {
|
|
199
|
+
try {
|
|
200
|
+
const params = normalizeArgs(args, [
|
|
201
|
+
{ key: 'assetPath', required: true },
|
|
202
|
+
{ key: 'tags', required: true }
|
|
203
|
+
]);
|
|
204
|
+
const res = await tools.assetTools.setTags({ assetPath: params.assetPath, tags: params.tags });
|
|
205
|
+
return ResponseFactory.success(res, 'Tags set successfully');
|
|
206
|
+
}
|
|
207
|
+
catch (err) {
|
|
208
|
+
const message = String(err?.message || err || '').toLowerCase();
|
|
209
|
+
if (message.includes('not_implemented') ||
|
|
210
|
+
message.includes('not implemented') ||
|
|
211
|
+
message.includes('unknown action') ||
|
|
212
|
+
message.includes('unknown subaction')) {
|
|
213
|
+
return ResponseFactory.error('NOT_IMPLEMENTED', 'Asset tag writes are not implemented by the automation plugin.');
|
|
214
|
+
}
|
|
215
|
+
throw err;
|
|
216
|
+
}
|
|
160
217
|
}
|
|
161
|
-
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
218
|
+
case 'get_metadata': {
|
|
219
|
+
const params = normalizeArgs(args, [
|
|
220
|
+
{ key: 'assetPath', required: true }
|
|
221
|
+
]);
|
|
222
|
+
const res = await tools.assetTools.getMetadata({ assetPath: params.assetPath });
|
|
223
|
+
const tags = res.tags || {};
|
|
224
|
+
const metadata = res.metadata || {};
|
|
225
|
+
const merged = { ...tags, ...metadata };
|
|
226
|
+
const tagCount = Object.keys(merged).length;
|
|
227
|
+
const cleanRes = cleanObject(res);
|
|
228
|
+
cleanRes.message = `Metadata retrieved (${tagCount} items)`;
|
|
229
|
+
cleanRes.tags = tags;
|
|
230
|
+
if (Object.keys(metadata).length > 0) {
|
|
231
|
+
cleanRes.metadata = metadata;
|
|
165
232
|
}
|
|
233
|
+
return ResponseFactory.success(cleanRes, cleanRes.message);
|
|
166
234
|
}
|
|
167
|
-
|
|
168
|
-
|
|
235
|
+
case 'set_metadata': {
|
|
236
|
+
const res = await executeAutomationRequest(tools, 'set_metadata', args);
|
|
237
|
+
return ResponseFactory.success(res, 'Metadata set successfully');
|
|
169
238
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
173
|
-
case 'generate_lods': {
|
|
174
|
-
const params = normalizeArgs(args, [
|
|
175
|
-
{ key: 'assetPath', required: true },
|
|
176
|
-
{ key: 'lodCount', required: true }
|
|
177
|
-
]);
|
|
178
|
-
return cleanObject(await tools.assetTools.generateLODs({
|
|
179
|
-
assetPath: params.assetPath,
|
|
180
|
-
lodCount: params.lodCount
|
|
181
|
-
}));
|
|
182
|
-
}
|
|
183
|
-
case 'create_thumbnail': {
|
|
184
|
-
const params = normalizeArgs(args, [
|
|
185
|
-
{ key: 'assetPath', required: true },
|
|
186
|
-
{ key: 'width' },
|
|
187
|
-
{ key: 'height' }
|
|
188
|
-
]);
|
|
189
|
-
const res = await tools.assetTools.createThumbnail({
|
|
190
|
-
assetPath: params.assetPath,
|
|
191
|
-
width: params.width,
|
|
192
|
-
height: params.height
|
|
193
|
-
});
|
|
194
|
-
return cleanObject(res);
|
|
195
|
-
}
|
|
196
|
-
case 'set_tags': {
|
|
197
|
-
try {
|
|
239
|
+
case 'validate':
|
|
240
|
+
case 'validate_asset': {
|
|
198
241
|
const params = normalizeArgs(args, [
|
|
199
|
-
{ key: 'assetPath', required: true }
|
|
200
|
-
{ key: 'tags', required: true }
|
|
242
|
+
{ key: 'assetPath', required: true }
|
|
201
243
|
]);
|
|
202
|
-
const res = await tools.assetTools.
|
|
203
|
-
return
|
|
244
|
+
const res = await tools.assetTools.validate({ assetPath: params.assetPath });
|
|
245
|
+
return ResponseFactory.success(res, 'Asset validation complete');
|
|
246
|
+
}
|
|
247
|
+
case 'generate_report': {
|
|
248
|
+
const params = normalizeArgs(args, [
|
|
249
|
+
{ key: 'directory' },
|
|
250
|
+
{ key: 'reportType' },
|
|
251
|
+
{ key: 'outputPath' }
|
|
252
|
+
]);
|
|
253
|
+
const res = await tools.assetTools.generateReport({
|
|
254
|
+
directory: params.directory,
|
|
255
|
+
reportType: params.reportType,
|
|
256
|
+
outputPath: params.outputPath
|
|
257
|
+
});
|
|
258
|
+
return ResponseFactory.success(res, 'Report generated successfully');
|
|
204
259
|
}
|
|
205
|
-
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
260
|
+
case 'create_material_instance': {
|
|
261
|
+
const res = await executeAutomationRequest(tools, 'create_material_instance', args, 'Automation bridge not available for create_material_instance');
|
|
262
|
+
const result = res?.result ?? res ?? {};
|
|
263
|
+
const errorCode = typeof result.error === 'string' ? result.error.toUpperCase() : '';
|
|
264
|
+
const message = typeof result.message === 'string' ? result.message : '';
|
|
265
|
+
if (errorCode === 'PARENT_NOT_FOUND' || message.toLowerCase().includes('parent material not found')) {
|
|
211
266
|
return cleanObject({
|
|
212
267
|
success: false,
|
|
213
|
-
error: '
|
|
214
|
-
message:
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
tags: args.tags
|
|
268
|
+
error: 'PARENT_NOT_FOUND',
|
|
269
|
+
message: message || 'Parent material not found',
|
|
270
|
+
path: result.path,
|
|
271
|
+
parentMaterial: args.parentMaterial
|
|
218
272
|
});
|
|
219
273
|
}
|
|
220
|
-
|
|
274
|
+
return ResponseFactory.success(res, 'Material instance created successfully');
|
|
221
275
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
276
|
+
case 'search_assets': {
|
|
277
|
+
const params = normalizeArgs(args, [
|
|
278
|
+
{ key: 'classNames' },
|
|
279
|
+
{ key: 'packagePaths' },
|
|
280
|
+
{ key: 'recursivePaths' },
|
|
281
|
+
{ key: 'recursiveClasses' },
|
|
282
|
+
{ key: 'limit' }
|
|
283
|
+
]);
|
|
284
|
+
const res = await tools.assetTools.searchAssets({
|
|
285
|
+
classNames: params.classNames,
|
|
286
|
+
packagePaths: params.packagePaths,
|
|
287
|
+
recursivePaths: params.recursivePaths,
|
|
288
|
+
recursiveClasses: params.recursiveClasses,
|
|
289
|
+
limit: params.limit
|
|
290
|
+
});
|
|
291
|
+
return ResponseFactory.success(res, 'Assets found');
|
|
237
292
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
const message = typeof result.message === 'string' ? result.message : '';
|
|
270
|
-
if (errorCode === 'PARENT_NOT_FOUND' || message.toLowerCase().includes('parent material not found')) {
|
|
271
|
-
return cleanObject({
|
|
272
|
-
success: false,
|
|
273
|
-
error: 'PARENT_NOT_FOUND',
|
|
274
|
-
message: message || 'Parent material not found',
|
|
275
|
-
path: result.path,
|
|
276
|
-
parentMaterial: args.parentMaterial
|
|
293
|
+
case 'find_by_tag': {
|
|
294
|
+
const params = normalizeArgs(args, [
|
|
295
|
+
{ key: 'tag', required: true },
|
|
296
|
+
{ key: 'value' }
|
|
297
|
+
]);
|
|
298
|
+
const res = await tools.assetTools.findByTag({ tag: params.tag, value: params.value });
|
|
299
|
+
return ResponseFactory.success(res, 'Assets found by tag');
|
|
300
|
+
}
|
|
301
|
+
case 'get_dependencies': {
|
|
302
|
+
const params = normalizeArgs(args, [
|
|
303
|
+
{ key: 'assetPath', required: true },
|
|
304
|
+
{ key: 'recursive' }
|
|
305
|
+
]);
|
|
306
|
+
const res = await tools.assetTools.getDependencies({ assetPath: params.assetPath, recursive: params.recursive });
|
|
307
|
+
return ResponseFactory.success(res, 'Dependencies retrieved');
|
|
308
|
+
}
|
|
309
|
+
case 'get_source_control_state': {
|
|
310
|
+
const params = normalizeArgs(args, [
|
|
311
|
+
{ key: 'assetPath', required: true }
|
|
312
|
+
]);
|
|
313
|
+
const res = await tools.assetTools.getSourceControlState({ assetPath: params.assetPath });
|
|
314
|
+
return ResponseFactory.success(res, 'Source control state retrieved');
|
|
315
|
+
}
|
|
316
|
+
case 'analyze_graph': {
|
|
317
|
+
const params = normalizeArgs(args, [
|
|
318
|
+
{ key: 'assetPath', required: true },
|
|
319
|
+
{ key: 'maxDepth' }
|
|
320
|
+
]);
|
|
321
|
+
const res = await executeAutomationRequest(tools, 'get_asset_graph', {
|
|
322
|
+
assetPath: params.assetPath,
|
|
323
|
+
maxDepth: params.maxDepth
|
|
277
324
|
});
|
|
325
|
+
return ResponseFactory.success(res, 'Graph analysis complete');
|
|
278
326
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
}
|
|
298
|
-
case 'find_by_tag': {
|
|
299
|
-
const params = normalizeArgs(args, [
|
|
300
|
-
{ key: 'tag', required: true },
|
|
301
|
-
{ key: 'value' }
|
|
302
|
-
]);
|
|
303
|
-
return tools.assetTools.findByTag({ tag: params.tag, value: params.value });
|
|
304
|
-
}
|
|
305
|
-
case 'get_dependencies': {
|
|
306
|
-
const params = normalizeArgs(args, [
|
|
307
|
-
{ key: 'assetPath', required: true },
|
|
308
|
-
{ key: 'recursive' }
|
|
309
|
-
]);
|
|
310
|
-
const res = await tools.assetTools.getDependencies({ assetPath: params.assetPath, recursive: params.recursive });
|
|
311
|
-
return cleanObject(res);
|
|
312
|
-
}
|
|
313
|
-
case 'get_source_control_state': {
|
|
314
|
-
const params = normalizeArgs(args, [
|
|
315
|
-
{ key: 'assetPath', required: true }
|
|
316
|
-
]);
|
|
317
|
-
const res = await tools.assetTools.getSourceControlState({ assetPath: params.assetPath });
|
|
318
|
-
return cleanObject(res);
|
|
319
|
-
}
|
|
320
|
-
case 'analyze_graph': {
|
|
321
|
-
const params = normalizeArgs(args, [
|
|
322
|
-
{ key: 'assetPath', required: true },
|
|
323
|
-
{ key: 'maxDepth' }
|
|
324
|
-
]);
|
|
325
|
-
const res = await executeAutomationRequest(tools, 'get_asset_graph', {
|
|
326
|
-
assetPath: params.assetPath,
|
|
327
|
-
maxDepth: params.maxDepth
|
|
328
|
-
});
|
|
329
|
-
return cleanObject(res);
|
|
330
|
-
}
|
|
331
|
-
case 'create_render_target': {
|
|
332
|
-
const params = normalizeArgs(args, [
|
|
333
|
-
{ key: 'name', required: true },
|
|
334
|
-
{ key: 'packagePath', aliases: ['path'], default: '/Game' },
|
|
335
|
-
{ key: 'width' },
|
|
336
|
-
{ key: 'height' },
|
|
337
|
-
{ key: 'format' }
|
|
338
|
-
]);
|
|
339
|
-
const res = await executeAutomationRequest(tools, 'manage_render', {
|
|
340
|
-
subAction: 'create_render_target',
|
|
341
|
-
name: params.name,
|
|
342
|
-
packagePath: params.packagePath,
|
|
343
|
-
width: params.width,
|
|
344
|
-
height: params.height,
|
|
345
|
-
format: params.format,
|
|
346
|
-
save: true
|
|
347
|
-
});
|
|
348
|
-
return cleanObject(res);
|
|
349
|
-
}
|
|
350
|
-
case 'nanite_rebuild_mesh': {
|
|
351
|
-
const params = normalizeArgs(args, [
|
|
352
|
-
{ key: 'assetPath', aliases: ['meshPath'], required: true }
|
|
353
|
-
]);
|
|
354
|
-
const res = await executeAutomationRequest(tools, 'manage_render', {
|
|
355
|
-
subAction: 'nanite_rebuild_mesh',
|
|
356
|
-
assetPath: params.assetPath
|
|
357
|
-
});
|
|
358
|
-
return cleanObject(res);
|
|
359
|
-
}
|
|
360
|
-
case 'fixup_redirectors': {
|
|
361
|
-
const directoryRaw = typeof args.directory === 'string' && args.directory.trim().length > 0
|
|
362
|
-
? args.directory.trim()
|
|
363
|
-
: (typeof args.directoryPath === 'string' && args.directoryPath.trim().length > 0
|
|
364
|
-
? args.directoryPath.trim()
|
|
365
|
-
: '');
|
|
366
|
-
const payload = {};
|
|
367
|
-
if (directoryRaw) {
|
|
368
|
-
payload.directoryPath = directoryRaw;
|
|
327
|
+
case 'create_render_target': {
|
|
328
|
+
const params = normalizeArgs(args, [
|
|
329
|
+
{ key: 'name', required: true },
|
|
330
|
+
{ key: 'packagePath', aliases: ['path'], default: '/Game' },
|
|
331
|
+
{ key: 'width' },
|
|
332
|
+
{ key: 'height' },
|
|
333
|
+
{ key: 'format' }
|
|
334
|
+
]);
|
|
335
|
+
const res = await executeAutomationRequest(tools, 'manage_render', {
|
|
336
|
+
subAction: 'create_render_target',
|
|
337
|
+
name: params.name,
|
|
338
|
+
packagePath: params.packagePath,
|
|
339
|
+
width: params.width,
|
|
340
|
+
height: params.height,
|
|
341
|
+
format: params.format,
|
|
342
|
+
save: true
|
|
343
|
+
});
|
|
344
|
+
return ResponseFactory.success(res, 'Render target created successfully');
|
|
369
345
|
}
|
|
370
|
-
|
|
371
|
-
|
|
346
|
+
case 'nanite_rebuild_mesh': {
|
|
347
|
+
const params = normalizeArgs(args, [
|
|
348
|
+
{ key: 'assetPath', aliases: ['meshPath'], required: true }
|
|
349
|
+
]);
|
|
350
|
+
const res = await executeAutomationRequest(tools, 'manage_render', {
|
|
351
|
+
subAction: 'nanite_rebuild_mesh',
|
|
352
|
+
assetPath: params.assetPath
|
|
353
|
+
});
|
|
354
|
+
return ResponseFactory.success(res, 'Nanite mesh rebuilt successfully');
|
|
372
355
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
'
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
'
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
action: action || 'manage_asset',
|
|
490
|
-
assetPath: args.assetPath ?? args.path
|
|
356
|
+
case 'fixup_redirectors': {
|
|
357
|
+
const directoryRaw = typeof args.directory === 'string' && args.directory.trim().length > 0
|
|
358
|
+
? args.directory.trim()
|
|
359
|
+
: (typeof args.directoryPath === 'string' && args.directoryPath.trim().length > 0
|
|
360
|
+
? args.directoryPath.trim()
|
|
361
|
+
: '');
|
|
362
|
+
const payload = {};
|
|
363
|
+
if (directoryRaw) {
|
|
364
|
+
payload.directoryPath = directoryRaw;
|
|
365
|
+
}
|
|
366
|
+
if (typeof args.checkoutFiles === 'boolean') {
|
|
367
|
+
payload.checkoutFiles = args.checkoutFiles;
|
|
368
|
+
}
|
|
369
|
+
const res = await executeAutomationRequest(tools, 'fixup_redirectors', payload);
|
|
370
|
+
return ResponseFactory.success(res, 'Redirectors fixed up successfully');
|
|
371
|
+
}
|
|
372
|
+
case 'add_material_parameter': {
|
|
373
|
+
const params = normalizeArgs(args, [
|
|
374
|
+
{ key: 'assetPath', required: true },
|
|
375
|
+
{ key: 'parameterName', aliases: ['name'], required: true },
|
|
376
|
+
{ key: 'parameterType', aliases: ['type'] },
|
|
377
|
+
{ key: 'value', aliases: ['defaultValue'] }
|
|
378
|
+
]);
|
|
379
|
+
const res = await executeAutomationRequest(tools, 'add_material_parameter', {
|
|
380
|
+
assetPath: params.assetPath,
|
|
381
|
+
name: params.parameterName,
|
|
382
|
+
type: params.parameterType,
|
|
383
|
+
value: params.value
|
|
384
|
+
});
|
|
385
|
+
return ResponseFactory.success(res, 'Material parameter added successfully');
|
|
386
|
+
}
|
|
387
|
+
case 'list_instances': {
|
|
388
|
+
const params = normalizeArgs(args, [
|
|
389
|
+
{ key: 'assetPath', required: true }
|
|
390
|
+
]);
|
|
391
|
+
const res = await executeAutomationRequest(tools, 'list_instances', {
|
|
392
|
+
assetPath: params.assetPath
|
|
393
|
+
});
|
|
394
|
+
return ResponseFactory.success(res, 'Instances listed successfully');
|
|
395
|
+
}
|
|
396
|
+
case 'reset_instance_parameters': {
|
|
397
|
+
const params = normalizeArgs(args, [
|
|
398
|
+
{ key: 'assetPath', required: true }
|
|
399
|
+
]);
|
|
400
|
+
const res = await executeAutomationRequest(tools, 'reset_instance_parameters', {
|
|
401
|
+
assetPath: params.assetPath
|
|
402
|
+
});
|
|
403
|
+
return ResponseFactory.success(res, 'Instance parameters reset successfully');
|
|
404
|
+
}
|
|
405
|
+
case 'exists': {
|
|
406
|
+
const params = normalizeArgs(args, [
|
|
407
|
+
{ key: 'assetPath', required: true }
|
|
408
|
+
]);
|
|
409
|
+
const res = await executeAutomationRequest(tools, 'exists', {
|
|
410
|
+
assetPath: params.assetPath
|
|
411
|
+
});
|
|
412
|
+
return ResponseFactory.success(res, 'Asset existence check complete');
|
|
413
|
+
}
|
|
414
|
+
case 'get_material_stats': {
|
|
415
|
+
const params = normalizeArgs(args, [
|
|
416
|
+
{ key: 'assetPath', required: true }
|
|
417
|
+
]);
|
|
418
|
+
const res = await executeAutomationRequest(tools, 'get_material_stats', {
|
|
419
|
+
assetPath: params.assetPath
|
|
420
|
+
});
|
|
421
|
+
return ResponseFactory.success(res, 'Material stats retrieved');
|
|
422
|
+
}
|
|
423
|
+
case 'rebuild_material': {
|
|
424
|
+
const params = normalizeArgs(args, [
|
|
425
|
+
{ key: 'assetPath', required: true }
|
|
426
|
+
]);
|
|
427
|
+
const res = await executeAutomationRequest(tools, 'rebuild_material', {
|
|
428
|
+
assetPath: params.assetPath
|
|
429
|
+
});
|
|
430
|
+
return ResponseFactory.success(res, 'Material rebuilt successfully');
|
|
431
|
+
}
|
|
432
|
+
case 'add_material_node': {
|
|
433
|
+
const materialNodeAliases = {
|
|
434
|
+
'Multiply': 'MaterialExpressionMultiply',
|
|
435
|
+
'Add': 'MaterialExpressionAdd',
|
|
436
|
+
'Subtract': 'MaterialExpressionSubtract',
|
|
437
|
+
'Divide': 'MaterialExpressionDivide',
|
|
438
|
+
'Power': 'MaterialExpressionPower',
|
|
439
|
+
'Clamp': 'MaterialExpressionClamp',
|
|
440
|
+
'Constant': 'MaterialExpressionConstant',
|
|
441
|
+
'Constant2Vector': 'MaterialExpressionConstant2Vector',
|
|
442
|
+
'Constant3Vector': 'MaterialExpressionConstant3Vector',
|
|
443
|
+
'Constant4Vector': 'MaterialExpressionConstant4Vector',
|
|
444
|
+
'TextureSample': 'MaterialExpressionTextureSample',
|
|
445
|
+
'TextureCoordinate': 'MaterialExpressionTextureCoordinate',
|
|
446
|
+
'Panner': 'MaterialExpressionPanner',
|
|
447
|
+
'Rotator': 'MaterialExpressionRotator',
|
|
448
|
+
'Lerp': 'MaterialExpressionLinearInterpolate',
|
|
449
|
+
'LinearInterpolate': 'MaterialExpressionLinearInterpolate',
|
|
450
|
+
'Sine': 'MaterialExpressionSine',
|
|
451
|
+
'Cosine': 'MaterialExpressionCosine',
|
|
452
|
+
'Append': 'MaterialExpressionAppendVector',
|
|
453
|
+
'AppendVector': 'MaterialExpressionAppendVector',
|
|
454
|
+
'ComponentMask': 'MaterialExpressionComponentMask',
|
|
455
|
+
'Fresnel': 'MaterialExpressionFresnel',
|
|
456
|
+
'Time': 'MaterialExpressionTime',
|
|
457
|
+
'ScalarParameter': 'MaterialExpressionScalarParameter',
|
|
458
|
+
'VectorParameter': 'MaterialExpressionVectorParameter',
|
|
459
|
+
'StaticSwitchParameter': 'MaterialExpressionStaticSwitchParameter'
|
|
460
|
+
};
|
|
461
|
+
const params = normalizeArgs(args, [
|
|
462
|
+
{ key: 'assetPath', required: true },
|
|
463
|
+
{ key: 'nodeType', aliases: ['type'], required: true, map: materialNodeAliases },
|
|
464
|
+
{ key: 'posX' },
|
|
465
|
+
{ key: 'posY' }
|
|
466
|
+
]);
|
|
467
|
+
const res = await executeAutomationRequest(tools, 'add_material_node', {
|
|
468
|
+
assetPath: params.assetPath,
|
|
469
|
+
nodeType: params.nodeType,
|
|
470
|
+
posX: params.posX,
|
|
471
|
+
posY: params.posY
|
|
491
472
|
});
|
|
473
|
+
return ResponseFactory.success(res, 'Material node added successfully');
|
|
492
474
|
}
|
|
493
|
-
|
|
475
|
+
default:
|
|
476
|
+
const res = await executeAutomationRequest(tools, action || 'manage_asset', args);
|
|
477
|
+
const result = res?.result ?? res ?? {};
|
|
478
|
+
const errorCode = typeof result.error === 'string' ? result.error.toUpperCase() : '';
|
|
479
|
+
const message = typeof result.message === 'string' ? result.message : '';
|
|
480
|
+
if (errorCode === 'INVALID_SUBACTION' || message.toLowerCase().includes('unknown subaction')) {
|
|
481
|
+
return cleanObject({
|
|
482
|
+
success: false,
|
|
483
|
+
error: 'INVALID_SUBACTION',
|
|
484
|
+
message: 'Asset action not recognized by the automation plugin.',
|
|
485
|
+
action: action || 'manage_asset',
|
|
486
|
+
assetPath: args.assetPath ?? args.path
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
return ResponseFactory.success(res, 'Asset action executed successfully');
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
catch (error) {
|
|
493
|
+
return ResponseFactory.error(error);
|
|
494
494
|
}
|
|
495
495
|
}
|
|
496
496
|
//# sourceMappingURL=asset-handlers.js.map
|