unreal-engine-mcp-server 0.4.7 → 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.
- package/.env.example +26 -0
- package/.env.production +38 -7
- package/.eslintrc.json +0 -54
- package/.eslintrc.override.json +8 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +94 -0
- package/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +56 -0
- package/.github/copilot-instructions.md +478 -45
- package/.github/dependabot.yml +19 -0
- package/.github/labeler.yml +24 -0
- package/.github/labels.yml +70 -0
- package/.github/pull_request_template.md +42 -0
- package/.github/release-drafter-config.yml +51 -0
- package/.github/workflows/auto-merge.yml +38 -0
- package/.github/workflows/ci.yml +38 -0
- package/.github/workflows/dependency-review.yml +17 -0
- package/.github/workflows/gemini-issue-triage.yml +172 -0
- package/.github/workflows/greetings.yml +27 -0
- package/.github/workflows/labeler.yml +17 -0
- package/.github/workflows/links.yml +80 -0
- package/.github/workflows/pr-size-labeler.yml +137 -0
- package/.github/workflows/publish-mcp.yml +13 -7
- package/.github/workflows/release-drafter.yml +23 -0
- package/.github/workflows/release.yml +112 -0
- package/.github/workflows/semantic-pull-request.yml +35 -0
- package/.github/workflows/smoke-test.yml +36 -0
- package/.github/workflows/stale.yml +28 -0
- package/CHANGELOG.md +338 -31
- package/CONTRIBUTING.md +140 -0
- package/GEMINI.md +115 -0
- package/Public/Plugin_setup_guide.mp4 +0 -0
- package/README.md +189 -128
- package/claude_desktop_config_example.json +7 -6
- package/dist/automation/bridge.d.ts +50 -0
- package/dist/automation/bridge.js +452 -0
- package/dist/automation/connection-manager.d.ts +23 -0
- package/dist/automation/connection-manager.js +107 -0
- package/dist/automation/handshake.d.ts +11 -0
- package/dist/automation/handshake.js +89 -0
- package/dist/automation/index.d.ts +3 -0
- package/dist/automation/index.js +3 -0
- package/dist/automation/message-handler.d.ts +12 -0
- package/dist/automation/message-handler.js +149 -0
- package/dist/automation/request-tracker.d.ts +25 -0
- package/dist/automation/request-tracker.js +98 -0
- package/dist/automation/types.d.ts +130 -0
- package/dist/automation/types.js +2 -0
- package/dist/cli.js +32 -5
- package/dist/config.d.ts +26 -0
- package/dist/config.js +59 -0
- package/dist/constants.d.ts +16 -0
- package/dist/constants.js +16 -0
- package/dist/graphql/loaders.d.ts +64 -0
- package/dist/graphql/loaders.js +117 -0
- package/dist/graphql/resolvers.d.ts +268 -0
- package/dist/graphql/resolvers.js +746 -0
- package/dist/graphql/schema.d.ts +5 -0
- package/dist/graphql/schema.js +437 -0
- package/dist/graphql/server.d.ts +26 -0
- package/dist/graphql/server.js +117 -0
- package/dist/graphql/types.d.ts +9 -0
- package/dist/graphql/types.js +2 -0
- package/dist/handlers/resource-handlers.d.ts +20 -0
- package/dist/handlers/resource-handlers.js +180 -0
- package/dist/index.d.ts +33 -18
- package/dist/index.js +130 -619
- package/dist/resources/actors.d.ts +17 -12
- package/dist/resources/actors.js +56 -76
- package/dist/resources/assets.d.ts +6 -14
- package/dist/resources/assets.js +115 -147
- package/dist/resources/levels.d.ts +13 -13
- package/dist/resources/levels.js +25 -34
- package/dist/server/resource-registry.d.ts +20 -0
- package/dist/server/resource-registry.js +37 -0
- package/dist/server/tool-registry.d.ts +23 -0
- package/dist/server/tool-registry.js +322 -0
- package/dist/server-setup.d.ts +20 -0
- package/dist/server-setup.js +71 -0
- package/dist/services/health-monitor.d.ts +34 -0
- package/dist/services/health-monitor.js +105 -0
- package/dist/services/metrics-server.d.ts +11 -0
- package/dist/services/metrics-server.js +105 -0
- package/dist/tools/actors.d.ts +163 -9
- package/dist/tools/actors.js +356 -311
- package/dist/tools/animation.d.ts +135 -4
- package/dist/tools/animation.js +510 -411
- package/dist/tools/assets.d.ts +75 -29
- package/dist/tools/assets.js +265 -284
- package/dist/tools/audio.d.ts +102 -42
- package/dist/tools/audio.js +272 -685
- package/dist/tools/base-tool.d.ts +17 -0
- package/dist/tools/base-tool.js +46 -0
- package/dist/tools/behavior-tree.d.ts +94 -0
- package/dist/tools/behavior-tree.js +39 -0
- package/dist/tools/blueprint.d.ts +208 -126
- package/dist/tools/blueprint.js +685 -832
- package/dist/tools/consolidated-tool-definitions.d.ts +5462 -1781
- package/dist/tools/consolidated-tool-definitions.js +829 -496
- package/dist/tools/consolidated-tool-handlers.d.ts +2 -1
- package/dist/tools/consolidated-tool-handlers.js +198 -1027
- package/dist/tools/debug.d.ts +143 -85
- package/dist/tools/debug.js +234 -180
- package/dist/tools/dynamic-handler-registry.d.ts +13 -0
- package/dist/tools/dynamic-handler-registry.js +23 -0
- package/dist/tools/editor.d.ts +30 -83
- package/dist/tools/editor.js +247 -244
- package/dist/tools/engine.d.ts +10 -4
- package/dist/tools/engine.js +13 -5
- package/dist/tools/environment.d.ts +30 -0
- package/dist/tools/environment.js +267 -0
- package/dist/tools/foliage.d.ts +65 -99
- package/dist/tools/foliage.js +221 -331
- package/dist/tools/handlers/actor-handlers.d.ts +3 -0
- package/dist/tools/handlers/actor-handlers.js +227 -0
- package/dist/tools/handlers/animation-handlers.d.ts +3 -0
- package/dist/tools/handlers/animation-handlers.js +185 -0
- package/dist/tools/handlers/argument-helper.d.ts +16 -0
- package/dist/tools/handlers/argument-helper.js +80 -0
- package/dist/tools/handlers/asset-handlers.d.ts +3 -0
- package/dist/tools/handlers/asset-handlers.js +496 -0
- package/dist/tools/handlers/audio-handlers.d.ts +3 -0
- package/dist/tools/handlers/audio-handlers.js +166 -0
- package/dist/tools/handlers/blueprint-handlers.d.ts +4 -0
- package/dist/tools/handlers/blueprint-handlers.js +358 -0
- package/dist/tools/handlers/common-handlers.d.ts +14 -0
- package/dist/tools/handlers/common-handlers.js +56 -0
- package/dist/tools/handlers/editor-handlers.d.ts +3 -0
- package/dist/tools/handlers/editor-handlers.js +119 -0
- package/dist/tools/handlers/effect-handlers.d.ts +3 -0
- package/dist/tools/handlers/effect-handlers.js +171 -0
- package/dist/tools/handlers/environment-handlers.d.ts +3 -0
- package/dist/tools/handlers/environment-handlers.js +170 -0
- package/dist/tools/handlers/graph-handlers.d.ts +3 -0
- package/dist/tools/handlers/graph-handlers.js +90 -0
- package/dist/tools/handlers/input-handlers.d.ts +3 -0
- package/dist/tools/handlers/input-handlers.js +21 -0
- package/dist/tools/handlers/inspect-handlers.d.ts +3 -0
- package/dist/tools/handlers/inspect-handlers.js +383 -0
- package/dist/tools/handlers/level-handlers.d.ts +3 -0
- package/dist/tools/handlers/level-handlers.js +237 -0
- package/dist/tools/handlers/lighting-handlers.d.ts +3 -0
- package/dist/tools/handlers/lighting-handlers.js +144 -0
- package/dist/tools/handlers/performance-handlers.d.ts +3 -0
- package/dist/tools/handlers/performance-handlers.js +130 -0
- package/dist/tools/handlers/pipeline-handlers.d.ts +3 -0
- package/dist/tools/handlers/pipeline-handlers.js +110 -0
- package/dist/tools/handlers/sequence-handlers.d.ts +3 -0
- package/dist/tools/handlers/sequence-handlers.js +376 -0
- package/dist/tools/handlers/system-handlers.d.ts +4 -0
- package/dist/tools/handlers/system-handlers.js +506 -0
- package/dist/tools/input.d.ts +19 -0
- package/dist/tools/input.js +89 -0
- package/dist/tools/introspection.d.ts +103 -40
- package/dist/tools/introspection.js +425 -568
- package/dist/tools/landscape.d.ts +54 -93
- package/dist/tools/landscape.js +284 -409
- package/dist/tools/level.d.ts +66 -27
- package/dist/tools/level.js +647 -675
- package/dist/tools/lighting.d.ts +77 -38
- package/dist/tools/lighting.js +445 -943
- package/dist/tools/logs.d.ts +3 -3
- package/dist/tools/logs.js +5 -57
- package/dist/tools/materials.d.ts +91 -24
- package/dist/tools/materials.js +194 -118
- package/dist/tools/niagara.d.ts +149 -39
- package/dist/tools/niagara.js +267 -182
- package/dist/tools/performance.d.ts +27 -13
- package/dist/tools/performance.js +203 -122
- package/dist/tools/physics.d.ts +32 -77
- package/dist/tools/physics.js +175 -582
- package/dist/tools/property-dictionary.d.ts +13 -0
- package/dist/tools/property-dictionary.js +82 -0
- package/dist/tools/sequence.d.ts +85 -60
- package/dist/tools/sequence.js +208 -747
- package/dist/tools/tool-definition-utils.d.ts +59 -0
- package/dist/tools/tool-definition-utils.js +35 -0
- package/dist/tools/ui.d.ts +64 -34
- package/dist/tools/ui.js +134 -214
- package/dist/types/automation-responses.d.ts +115 -0
- package/dist/types/automation-responses.js +2 -0
- package/dist/types/env.d.ts +0 -3
- package/dist/types/env.js +0 -7
- package/dist/types/responses.d.ts +249 -0
- package/dist/types/responses.js +2 -0
- package/dist/types/tool-interfaces.d.ts +898 -0
- package/dist/types/tool-interfaces.js +2 -0
- package/dist/types/tool-types.d.ts +183 -19
- package/dist/types/tool-types.js +0 -4
- package/dist/unreal-bridge.d.ts +24 -131
- package/dist/unreal-bridge.js +364 -1506
- package/dist/utils/command-validator.d.ts +9 -0
- package/dist/utils/command-validator.js +68 -0
- package/dist/utils/elicitation.d.ts +1 -1
- package/dist/utils/elicitation.js +12 -15
- package/dist/utils/error-handler.d.ts +2 -51
- package/dist/utils/error-handler.js +11 -87
- package/dist/utils/ini-reader.d.ts +3 -0
- package/dist/utils/ini-reader.js +69 -0
- package/dist/utils/logger.js +9 -6
- package/dist/utils/normalize.d.ts +3 -0
- package/dist/utils/normalize.js +56 -0
- package/dist/utils/path-security.d.ts +2 -0
- package/dist/utils/path-security.js +24 -0
- package/dist/utils/response-factory.d.ts +7 -0
- package/dist/utils/response-factory.js +27 -0
- package/dist/utils/response-validator.d.ts +3 -24
- package/dist/utils/response-validator.js +130 -81
- package/dist/utils/result-helpers.d.ts +4 -5
- package/dist/utils/result-helpers.js +15 -16
- package/dist/utils/safe-json.js +5 -11
- package/dist/utils/unreal-command-queue.d.ts +24 -0
- package/dist/utils/unreal-command-queue.js +120 -0
- package/dist/utils/validation.d.ts +0 -40
- package/dist/utils/validation.js +1 -78
- package/dist/wasm/index.d.ts +70 -0
- package/dist/wasm/index.js +535 -0
- package/docs/GraphQL-API.md +888 -0
- package/docs/Migration-Guide-v0.5.0.md +684 -0
- package/docs/Roadmap.md +53 -0
- package/docs/WebAssembly-Integration.md +628 -0
- package/docs/editor-plugin-extension.md +370 -0
- package/docs/handler-mapping.md +242 -0
- package/docs/native-automation-progress.md +128 -0
- package/docs/testing-guide.md +423 -0
- package/mcp-config-example.json +6 -6
- package/package.json +67 -28
- package/plugins/McpAutomationBridge/Config/FilterPlugin.ini +8 -0
- package/plugins/McpAutomationBridge/McpAutomationBridge.uplugin +64 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/McpAutomationBridge.Build.cs +189 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.cpp +22 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.h +30 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeHelpers.h +1983 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeModule.cpp +72 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSettings.cpp +46 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSubsystem.cpp +581 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AnimationHandlers.cpp +2394 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetQueryHandlers.cpp +300 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetWorkflowHandlers.cpp +2807 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AudioHandlers.cpp +1087 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BehaviorTreeHandlers.cpp +488 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.cpp +643 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.h +31 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintGraphHandlers.cpp +1184 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers.cpp +5652 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers_List.cpp +152 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ControlHandlers.cpp +2614 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_DebugHandlers.cpp +42 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EditorFunctionHandlers.cpp +1237 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EffectHandlers.cpp +1701 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EnvironmentHandlers.cpp +2145 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_FoliageHandlers.cpp +954 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InputHandlers.cpp +209 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InsightsHandlers.cpp +41 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LandscapeHandlers.cpp +1164 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LevelHandlers.cpp +762 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LightingHandlers.cpp +634 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LogHandlers.cpp +136 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_MaterialGraphHandlers.cpp +494 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraGraphHandlers.cpp +278 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraHandlers.cpp +625 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PerformanceHandlers.cpp +401 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PipelineHandlers.cpp +67 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ProcessRequest.cpp +735 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PropertyHandlers.cpp +2634 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_RenderHandlers.cpp +189 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.cpp +917 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.h +39 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequenceHandlers.cpp +2670 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequencerHandlers.cpp +519 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_TestHandlers.cpp +38 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_UiHandlers.cpp +668 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_WorldPartitionHandlers.cpp +346 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.cpp +1330 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.h +149 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpConnectionManager.cpp +783 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSettings.h +115 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSubsystem.h +796 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpConnectionManager.h +117 -0
- package/scripts/check-unreal-connection.mjs +19 -0
- package/scripts/clean-tmp.js +23 -0
- package/scripts/patch-wasm.js +26 -0
- package/scripts/run-all-tests.mjs +136 -0
- package/scripts/smoke-test.ts +94 -0
- package/scripts/sync-mcp-plugin.js +143 -0
- package/scripts/test-no-plugin-alternates.mjs +113 -0
- package/scripts/validate-server.js +46 -0
- package/scripts/verify-automation-bridge.js +200 -0
- package/server.json +58 -21
- package/src/automation/bridge.ts +558 -0
- package/src/automation/connection-manager.ts +130 -0
- package/src/automation/handshake.ts +99 -0
- package/src/automation/index.ts +2 -0
- package/src/automation/message-handler.ts +167 -0
- package/src/automation/request-tracker.ts +123 -0
- package/src/automation/types.ts +107 -0
- package/src/cli.ts +33 -6
- package/src/config.ts +73 -0
- package/src/constants.ts +19 -0
- package/src/graphql/loaders.ts +244 -0
- package/src/graphql/resolvers.ts +1008 -0
- package/src/graphql/schema.ts +452 -0
- package/src/graphql/server.ts +156 -0
- package/src/graphql/types.ts +10 -0
- package/src/handlers/resource-handlers.ts +186 -0
- package/src/index.ts +166 -664
- package/src/resources/actors.ts +58 -76
- package/src/resources/assets.ts +148 -134
- package/src/resources/levels.ts +28 -33
- package/src/server/resource-registry.ts +47 -0
- package/src/server/tool-registry.ts +354 -0
- package/src/server-setup.ts +114 -0
- package/src/services/health-monitor.ts +132 -0
- package/src/services/metrics-server.ts +142 -0
- package/src/tools/actors.ts +426 -323
- package/src/tools/animation.ts +672 -461
- package/src/tools/assets.ts +364 -289
- package/src/tools/audio.ts +323 -766
- package/src/tools/base-tool.ts +52 -0
- package/src/tools/behavior-tree.ts +45 -0
- package/src/tools/blueprint.ts +792 -970
- package/src/tools/consolidated-tool-definitions.ts +993 -515
- package/src/tools/consolidated-tool-handlers.ts +258 -1146
- package/src/tools/debug.ts +292 -187
- package/src/tools/dynamic-handler-registry.ts +33 -0
- package/src/tools/editor.ts +329 -253
- package/src/tools/engine.ts +14 -3
- package/src/tools/environment.ts +281 -0
- package/src/tools/foliage.ts +330 -392
- package/src/tools/handlers/actor-handlers.ts +265 -0
- package/src/tools/handlers/animation-handlers.ts +237 -0
- package/src/tools/handlers/argument-helper.ts +142 -0
- package/src/tools/handlers/asset-handlers.ts +532 -0
- package/src/tools/handlers/audio-handlers.ts +194 -0
- package/src/tools/handlers/blueprint-handlers.ts +380 -0
- package/src/tools/handlers/common-handlers.ts +87 -0
- package/src/tools/handlers/editor-handlers.ts +123 -0
- package/src/tools/handlers/effect-handlers.ts +220 -0
- package/src/tools/handlers/environment-handlers.ts +183 -0
- package/src/tools/handlers/graph-handlers.ts +116 -0
- package/src/tools/handlers/input-handlers.ts +28 -0
- package/src/tools/handlers/inspect-handlers.ts +450 -0
- package/src/tools/handlers/level-handlers.ts +252 -0
- package/src/tools/handlers/lighting-handlers.ts +147 -0
- package/src/tools/handlers/performance-handlers.ts +132 -0
- package/src/tools/handlers/pipeline-handlers.ts +127 -0
- package/src/tools/handlers/sequence-handlers.ts +415 -0
- package/src/tools/handlers/system-handlers.ts +564 -0
- package/src/tools/input.ts +101 -0
- package/src/tools/introspection.ts +493 -584
- package/src/tools/landscape.ts +418 -507
- package/src/tools/level.ts +786 -708
- package/src/tools/lighting.ts +588 -984
- package/src/tools/logs.ts +9 -57
- package/src/tools/materials.ts +237 -121
- package/src/tools/niagara.ts +335 -168
- package/src/tools/performance.ts +320 -169
- package/src/tools/physics.ts +274 -613
- package/src/tools/property-dictionary.ts +98 -0
- package/src/tools/sequence.ts +276 -820
- package/src/tools/tool-definition-utils.ts +35 -0
- package/src/tools/ui.ts +205 -283
- package/src/types/automation-responses.ts +119 -0
- package/src/types/env.ts +0 -10
- package/src/types/responses.ts +355 -0
- package/src/types/tool-interfaces.ts +250 -0
- package/src/types/tool-types.ts +243 -21
- package/src/unreal-bridge.ts +460 -1550
- package/src/utils/command-validator.ts +76 -0
- package/src/utils/elicitation.ts +10 -7
- package/src/utils/error-handler.ts +14 -90
- package/src/utils/ini-reader.ts +86 -0
- package/src/utils/logger.ts +8 -3
- package/src/utils/normalize.test.ts +162 -0
- package/src/utils/normalize.ts +60 -0
- package/src/utils/path-security.ts +43 -0
- package/src/utils/response-factory.ts +44 -0
- package/src/utils/response-validator.ts +176 -56
- package/src/utils/result-helpers.ts +21 -19
- package/src/utils/safe-json.test.ts +90 -0
- package/src/utils/safe-json.ts +14 -11
- package/src/utils/unreal-command-queue.ts +152 -0
- package/src/utils/validation.test.ts +184 -0
- package/src/utils/validation.ts +4 -1
- package/src/wasm/index.ts +838 -0
- package/test-server.mjs +100 -0
- package/tests/run-unreal-tool-tests.mjs +242 -14
- package/tests/test-animation.mjs +369 -0
- package/tests/test-asset-advanced.mjs +82 -0
- package/tests/test-asset-errors.mjs +35 -0
- package/tests/test-asset-graph.mjs +311 -0
- package/tests/test-audio.mjs +417 -0
- package/tests/test-automation-timeouts.mjs +98 -0
- package/tests/test-behavior-tree.mjs +444 -0
- package/tests/test-blueprint-graph.mjs +410 -0
- package/tests/test-blueprint.mjs +577 -0
- package/tests/test-client-mode.mjs +86 -0
- package/tests/test-console-command.mjs +56 -0
- package/tests/test-control-actor.mjs +425 -0
- package/tests/test-control-editor.mjs +112 -0
- package/tests/test-graphql.mjs +372 -0
- package/tests/test-input.mjs +349 -0
- package/tests/test-inspect.mjs +302 -0
- package/tests/test-landscape.mjs +316 -0
- package/tests/test-lighting.mjs +428 -0
- package/tests/test-manage-asset.mjs +438 -0
- package/tests/test-manage-level.mjs +89 -0
- package/tests/test-materials.mjs +356 -0
- package/tests/test-niagara.mjs +185 -0
- package/tests/test-no-inline-python.mjs +122 -0
- package/tests/test-performance.mjs +539 -0
- package/tests/test-plugin-handshake.mjs +82 -0
- package/tests/test-runner.mjs +933 -0
- package/tests/test-sequence.mjs +104 -0
- package/tests/test-system.mjs +96 -0
- package/tests/test-wasm.mjs +283 -0
- package/tests/test-world-partition.mjs +215 -0
- package/tsconfig.json +3 -3
- package/vitest.config.ts +35 -0
- package/wasm/Cargo.lock +363 -0
- package/wasm/Cargo.toml +42 -0
- package/wasm/LICENSE +21 -0
- package/wasm/README.md +253 -0
- package/wasm/src/dependency_resolver.rs +377 -0
- package/wasm/src/lib.rs +153 -0
- package/wasm/src/property_parser.rs +271 -0
- package/wasm/src/transform_math.rs +396 -0
- package/wasm/tests/integration.rs +109 -0
- package/.github/workflows/smithery-build.yml +0 -29
- package/dist/prompts/index.d.ts +0 -21
- package/dist/prompts/index.js +0 -217
- package/dist/tools/build_environment_advanced.d.ts +0 -65
- package/dist/tools/build_environment_advanced.js +0 -633
- package/dist/tools/rc.d.ts +0 -110
- package/dist/tools/rc.js +0 -437
- package/dist/tools/visual.d.ts +0 -40
- package/dist/tools/visual.js +0 -282
- package/dist/utils/http.d.ts +0 -6
- package/dist/utils/http.js +0 -151
- package/dist/utils/python-output.d.ts +0 -18
- package/dist/utils/python-output.js +0 -290
- package/dist/utils/python.d.ts +0 -2
- package/dist/utils/python.js +0 -4
- package/dist/utils/stdio-redirect.d.ts +0 -2
- package/dist/utils/stdio-redirect.js +0 -20
- package/docs/unreal-tool-test-cases.md +0 -574
- package/smithery.yaml +0 -29
- package/src/prompts/index.ts +0 -249
- package/src/tools/build_environment_advanced.ts +0 -732
- package/src/tools/rc.ts +0 -515
- package/src/tools/visual.ts +0 -281
- package/src/utils/http.ts +0 -187
- package/src/utils/python-output.ts +0 -351
- package/src/utils/python.ts +0 -3
- package/src/utils/stdio-redirect.ts +0 -18
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
import { cleanObject } from '../../utils/safe-json.js';
|
|
2
|
+
import { executeAutomationRequest } from './common-handlers.js';
|
|
3
|
+
import { normalizeArgs } from './argument-helper.js';
|
|
4
|
+
import { ResponseFactory } from '../../utils/response-factory.js';
|
|
5
|
+
export async function handleAssetTools(action, args, tools) {
|
|
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`;
|
|
46
|
+
}
|
|
47
|
+
return ResponseFactory.success({
|
|
48
|
+
assets: limitedAssets,
|
|
49
|
+
folders: folders,
|
|
50
|
+
totalCount: totalCount,
|
|
51
|
+
count: limitedAssets.length
|
|
52
|
+
}, message);
|
|
53
|
+
}
|
|
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');
|
|
60
|
+
}
|
|
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
|
+
}
|
|
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) {
|
|
112
|
+
const lastSlash = params.sourcePath.lastIndexOf('/');
|
|
113
|
+
const parentDir = lastSlash > 0 ? params.sourcePath.substring(0, lastSlash) : '/Game';
|
|
114
|
+
destinationPath = `${parentDir}/${params.newName}`;
|
|
115
|
+
}
|
|
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
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return cleanObject(res);
|
|
135
|
+
}
|
|
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');
|
|
151
|
+
}
|
|
152
|
+
case 'delete_assets':
|
|
153
|
+
case 'delete_asset':
|
|
154
|
+
case 'delete': {
|
|
155
|
+
let paths = [];
|
|
156
|
+
if (Array.isArray(args.paths)) {
|
|
157
|
+
paths = args.paths;
|
|
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');
|
|
173
|
+
}
|
|
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');
|
|
184
|
+
}
|
|
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');
|
|
197
|
+
}
|
|
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
|
+
}
|
|
217
|
+
}
|
|
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;
|
|
232
|
+
}
|
|
233
|
+
return ResponseFactory.success(cleanRes, cleanRes.message);
|
|
234
|
+
}
|
|
235
|
+
case 'set_metadata': {
|
|
236
|
+
const res = await executeAutomationRequest(tools, 'set_metadata', args);
|
|
237
|
+
return ResponseFactory.success(res, 'Metadata set successfully');
|
|
238
|
+
}
|
|
239
|
+
case 'validate':
|
|
240
|
+
case 'validate_asset': {
|
|
241
|
+
const params = normalizeArgs(args, [
|
|
242
|
+
{ key: 'assetPath', required: true }
|
|
243
|
+
]);
|
|
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');
|
|
259
|
+
}
|
|
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')) {
|
|
266
|
+
return cleanObject({
|
|
267
|
+
success: false,
|
|
268
|
+
error: 'PARENT_NOT_FOUND',
|
|
269
|
+
message: message || 'Parent material not found',
|
|
270
|
+
path: result.path,
|
|
271
|
+
parentMaterial: args.parentMaterial
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
return ResponseFactory.success(res, 'Material instance created successfully');
|
|
275
|
+
}
|
|
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');
|
|
292
|
+
}
|
|
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
|
|
324
|
+
});
|
|
325
|
+
return ResponseFactory.success(res, 'Graph analysis complete');
|
|
326
|
+
}
|
|
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');
|
|
345
|
+
}
|
|
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');
|
|
355
|
+
}
|
|
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
|
|
472
|
+
});
|
|
473
|
+
return ResponseFactory.success(res, 'Material node added successfully');
|
|
474
|
+
}
|
|
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
|
+
}
|
|
495
|
+
}
|
|
496
|
+
//# sourceMappingURL=asset-handlers.js.map
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { cleanObject } from '../../utils/safe-json.js';
|
|
2
|
+
import { requireNonEmptyString } from './common-handlers.js';
|
|
3
|
+
function toVec3Array(v) {
|
|
4
|
+
if (!v || typeof v !== 'object')
|
|
5
|
+
return undefined;
|
|
6
|
+
const x = Number(v.x);
|
|
7
|
+
const y = Number(v.y);
|
|
8
|
+
const z = Number(v.z);
|
|
9
|
+
if (!Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(z))
|
|
10
|
+
return undefined;
|
|
11
|
+
return [x, y, z];
|
|
12
|
+
}
|
|
13
|
+
function toRotArray(r) {
|
|
14
|
+
if (!r || typeof r !== 'object')
|
|
15
|
+
return undefined;
|
|
16
|
+
const pitch = Number(r.pitch);
|
|
17
|
+
const yaw = Number(r.yaw);
|
|
18
|
+
const roll = Number(r.roll);
|
|
19
|
+
if (!Number.isFinite(pitch) || !Number.isFinite(yaw) || !Number.isFinite(roll))
|
|
20
|
+
return undefined;
|
|
21
|
+
return [pitch, yaw, roll];
|
|
22
|
+
}
|
|
23
|
+
function getTimeoutMs() {
|
|
24
|
+
const envDefault = Number(process.env.MCP_AUTOMATION_REQUEST_TIMEOUT_MS ?? '120000');
|
|
25
|
+
return Number.isFinite(envDefault) && envDefault > 0 ? envDefault : 120000;
|
|
26
|
+
}
|
|
27
|
+
export async function handleAudioTools(action, args, tools) {
|
|
28
|
+
switch (action) {
|
|
29
|
+
case 'create_sound_cue':
|
|
30
|
+
requireNonEmptyString(args?.name, 'name', 'Missing required parameter: name');
|
|
31
|
+
requireNonEmptyString(args?.wavePath ?? args?.soundPath, 'soundPath', 'Missing required parameter: soundPath (or wavePath)');
|
|
32
|
+
return cleanObject(await tools.audioTools.createSoundCue({
|
|
33
|
+
name: args.name,
|
|
34
|
+
wavePath: args.wavePath ?? args.soundPath,
|
|
35
|
+
savePath: args.savePath,
|
|
36
|
+
settings: args.settings
|
|
37
|
+
}));
|
|
38
|
+
case 'play_sound_at_location':
|
|
39
|
+
requireNonEmptyString(args?.soundPath, 'soundPath', 'Missing required parameter: soundPath');
|
|
40
|
+
return cleanObject(await tools.audioTools.playSoundAtLocation({
|
|
41
|
+
soundPath: args.soundPath,
|
|
42
|
+
location: toVec3Array(args.location) ?? [0, 0, 0],
|
|
43
|
+
rotation: toRotArray(args.rotation),
|
|
44
|
+
volume: args.volume,
|
|
45
|
+
pitch: args.pitch,
|
|
46
|
+
startTime: args.startTime,
|
|
47
|
+
attenuationPath: args.attenuationPath,
|
|
48
|
+
concurrencyPath: args.concurrencyPath
|
|
49
|
+
}));
|
|
50
|
+
case 'play_sound_2d':
|
|
51
|
+
requireNonEmptyString(args?.soundPath, 'soundPath', 'Missing required parameter: soundPath');
|
|
52
|
+
return cleanObject(await tools.audioTools.playSound2D({
|
|
53
|
+
soundPath: args.soundPath,
|
|
54
|
+
volume: args.volume,
|
|
55
|
+
pitch: args.pitch,
|
|
56
|
+
startTime: args.startTime
|
|
57
|
+
}));
|
|
58
|
+
case 'create_audio_component':
|
|
59
|
+
requireNonEmptyString(args?.actorName, 'actorName', 'Missing required parameter: actorName');
|
|
60
|
+
requireNonEmptyString(args?.componentName, 'componentName', 'Missing required parameter: componentName');
|
|
61
|
+
requireNonEmptyString(args?.soundPath, 'soundPath', 'Missing required parameter: soundPath');
|
|
62
|
+
return cleanObject(await tools.audioTools.createAudioComponent({
|
|
63
|
+
actorName: args.actorName,
|
|
64
|
+
componentName: args.componentName,
|
|
65
|
+
soundPath: args.soundPath,
|
|
66
|
+
autoPlay: args.autoPlay,
|
|
67
|
+
is3D: args.is3D
|
|
68
|
+
}));
|
|
69
|
+
case 'set_sound_attenuation':
|
|
70
|
+
requireNonEmptyString(args?.name, 'name', 'Missing required parameter: name');
|
|
71
|
+
return cleanObject(await tools.audioTools.setSoundAttenuation({
|
|
72
|
+
name: args.name,
|
|
73
|
+
innerRadius: args.innerRadius,
|
|
74
|
+
falloffDistance: args.falloffDistance,
|
|
75
|
+
attenuationShape: args.attenuationShape,
|
|
76
|
+
falloffMode: args.falloffMode
|
|
77
|
+
}));
|
|
78
|
+
case 'create_sound_class':
|
|
79
|
+
requireNonEmptyString(args?.name, 'name', 'Missing required parameter: name');
|
|
80
|
+
return cleanObject(await tools.audioTools.createSoundClass({
|
|
81
|
+
name: args.name,
|
|
82
|
+
parentClass: args.parentClass,
|
|
83
|
+
properties: args.properties
|
|
84
|
+
}));
|
|
85
|
+
case 'create_sound_mix':
|
|
86
|
+
requireNonEmptyString(args?.name, 'name', 'Missing required parameter: name');
|
|
87
|
+
return cleanObject(await tools.audioTools.createSoundMix({
|
|
88
|
+
name: args.name,
|
|
89
|
+
classAdjusters: args.classAdjusters
|
|
90
|
+
}));
|
|
91
|
+
case 'push_sound_mix':
|
|
92
|
+
requireNonEmptyString(args?.mixName ?? args?.name, 'mixName', 'Missing required parameter: mixName (or name)');
|
|
93
|
+
return cleanObject(await tools.audioTools.pushSoundMix({
|
|
94
|
+
mixName: args.mixName ?? args.name
|
|
95
|
+
}));
|
|
96
|
+
case 'pop_sound_mix':
|
|
97
|
+
requireNonEmptyString(args?.mixName ?? args?.name, 'mixName', 'Missing required parameter: mixName (or name)');
|
|
98
|
+
return cleanObject(await tools.audioTools.popSoundMix({
|
|
99
|
+
mixName: args.mixName ?? args.name
|
|
100
|
+
}));
|
|
101
|
+
case 'create_ambient_sound':
|
|
102
|
+
requireNonEmptyString(args?.soundPath, 'soundPath', 'Missing required parameter: soundPath');
|
|
103
|
+
return cleanObject(await tools.audioTools.createAmbientSound({
|
|
104
|
+
soundPath: args.soundPath,
|
|
105
|
+
location: toVec3Array(args.location) ?? [0, 0, 0],
|
|
106
|
+
volume: args.volume,
|
|
107
|
+
pitch: args.pitch,
|
|
108
|
+
startTime: args.startTime,
|
|
109
|
+
attenuationPath: args.attenuationPath,
|
|
110
|
+
concurrencyPath: args.concurrencyPath
|
|
111
|
+
}));
|
|
112
|
+
case 'create_reverb_zone':
|
|
113
|
+
requireNonEmptyString(args?.name, 'name', 'Missing required parameter: name');
|
|
114
|
+
return cleanObject(await tools.audioTools.createReverbZone({
|
|
115
|
+
name: args.name,
|
|
116
|
+
location: toVec3Array(args.location) ?? [0, 0, 0],
|
|
117
|
+
size: toVec3Array(args.size) ?? [0, 0, 0],
|
|
118
|
+
reverbEffect: args.reverbEffect,
|
|
119
|
+
volume: args.volume,
|
|
120
|
+
fadeTime: args.fadeTime
|
|
121
|
+
}));
|
|
122
|
+
case 'enable_audio_analysis':
|
|
123
|
+
return cleanObject(await tools.audioTools.enableAudioAnalysis({
|
|
124
|
+
enabled: args.enabled,
|
|
125
|
+
fftSize: args.fftSize,
|
|
126
|
+
outputType: args.outputType
|
|
127
|
+
}));
|
|
128
|
+
case 'fade_sound':
|
|
129
|
+
requireNonEmptyString(args?.soundName, 'soundName', 'Missing required parameter: soundName');
|
|
130
|
+
return cleanObject(await tools.audioTools.fadeSound({
|
|
131
|
+
soundName: args.soundName,
|
|
132
|
+
targetVolume: args.targetVolume,
|
|
133
|
+
fadeTime: args.fadeTime,
|
|
134
|
+
fadeType: args.fadeType
|
|
135
|
+
}));
|
|
136
|
+
case 'set_doppler_effect':
|
|
137
|
+
return cleanObject(await tools.audioTools.setDopplerEffect({
|
|
138
|
+
enabled: args.enabled,
|
|
139
|
+
scale: args.scale
|
|
140
|
+
}));
|
|
141
|
+
case 'set_audio_occlusion':
|
|
142
|
+
return cleanObject(await tools.audioTools.setAudioOcclusion({
|
|
143
|
+
enabled: args.enabled,
|
|
144
|
+
lowPassFilterFrequency: args.lowPassFilterFrequency,
|
|
145
|
+
volumeAttenuation: args.volumeAttenuation
|
|
146
|
+
}));
|
|
147
|
+
case 'spawn_sound_at_location':
|
|
148
|
+
return cleanObject(await tools.automationBridge?.sendAutomationRequest('spawn_sound_at_location', args, { timeoutMs: getTimeoutMs() }));
|
|
149
|
+
case 'play_sound_attached':
|
|
150
|
+
return cleanObject(await tools.automationBridge?.sendAutomationRequest('play_sound_attached', args, { timeoutMs: getTimeoutMs() }));
|
|
151
|
+
case 'set_sound_mix_class_override':
|
|
152
|
+
return cleanObject(await tools.automationBridge?.sendAutomationRequest('set_sound_mix_class_override', args, { timeoutMs: getTimeoutMs() }));
|
|
153
|
+
case 'clear_sound_mix_class_override':
|
|
154
|
+
return cleanObject(await tools.automationBridge?.sendAutomationRequest('clear_sound_mix_class_override', args, { timeoutMs: getTimeoutMs() }));
|
|
155
|
+
case 'set_base_sound_mix':
|
|
156
|
+
return cleanObject(await tools.automationBridge?.sendAutomationRequest('set_base_sound_mix', args, { timeoutMs: getTimeoutMs() }));
|
|
157
|
+
case 'prime_sound':
|
|
158
|
+
return cleanObject(await tools.automationBridge?.sendAutomationRequest('prime_sound', args, { timeoutMs: getTimeoutMs() }));
|
|
159
|
+
case 'fade_sound_in':
|
|
160
|
+
case 'fade_sound_out':
|
|
161
|
+
return cleanObject(await tools.automationBridge?.sendAutomationRequest(action, args, { timeoutMs: getTimeoutMs() }));
|
|
162
|
+
default:
|
|
163
|
+
return cleanObject({ success: false, error: 'UNKNOWN_ACTION', message: `Unknown audio action: ${action}` });
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=audio-handlers.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ITools } from '../../types/tool-interfaces.js';
|
|
2
|
+
export declare function handleBlueprintTools(action: string, args: any, tools: ITools): Promise<any>;
|
|
3
|
+
export declare function handleBlueprintGet(args: any, tools: ITools): Promise<any>;
|
|
4
|
+
//# sourceMappingURL=blueprint-handlers.d.ts.map
|