unreal-engine-mcp-server 0.4.7 → 0.5.0
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.yml +148 -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 +23 -0
- package/.github/workflows/labeler.yml +16 -0
- package/.github/workflows/links.yml +80 -0
- package/.github/workflows/pr-size-labeler.yml +137 -0
- package/.github/workflows/publish-mcp.yml +12 -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 +267 -31
- package/CONTRIBUTING.md +140 -0
- package/README.md +166 -71
- 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 +27 -0
- package/dist/config.js +60 -0
- package/dist/constants.d.ts +12 -0
- package/dist/constants.js +12 -0
- package/dist/graphql/resolvers.d.ts +268 -0
- package/dist/graphql/resolvers.js +743 -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 +115 -0
- package/dist/graphql/types.d.ts +7 -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 +31 -18
- package/dist/index.js +119 -619
- package/dist/prompts/index.js +4 -4
- 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 +21 -0
- package/dist/server-setup.js +111 -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 +147 -9
- package/dist/tools/actors.js +350 -311
- package/dist/tools/animation.d.ts +135 -4
- package/dist/tools/animation.js +510 -411
- package/dist/tools/assets.d.ts +117 -19
- package/dist/tools/assets.js +259 -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/helpers.d.ts +29 -0
- package/dist/tools/blueprint/helpers.js +182 -0
- package/dist/tools/blueprint.d.ts +228 -118
- 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 +211 -1026
- package/dist/tools/debug.d.ts +143 -85
- package/dist/tools/debug.js +234 -180
- package/dist/tools/dynamic-handler-registry.d.ts +11 -0
- package/dist/tools/dynamic-handler-registry.js +101 -0
- package/dist/tools/editor.d.ts +139 -18
- package/dist/tools/editor.js +239 -244
- package/dist/tools/engine.d.ts +10 -4
- package/dist/tools/engine.js +13 -5
- package/dist/tools/environment.d.ts +36 -0
- package/dist/tools/environment.js +267 -0
- package/dist/tools/foliage.d.ts +105 -14
- package/dist/tools/foliage.js +219 -331
- package/dist/tools/handlers/actor-handlers.d.ts +3 -0
- package/dist/tools/handlers/actor-handlers.js +232 -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 +97 -36
- package/dist/tools/landscape.js +280 -409
- package/dist/tools/level.d.ts +130 -10
- package/dist/tools/level.js +639 -675
- package/dist/tools/lighting.d.ts +77 -38
- package/dist/tools/lighting.js +441 -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 +190 -118
- package/dist/tools/niagara.d.ts +149 -39
- package/dist/tools/niagara.js +232 -182
- package/dist/tools/performance.d.ts +27 -12
- package/dist/tools/performance.js +204 -122
- package/dist/tools/physics.d.ts +32 -77
- package/dist/tools/physics.js +171 -582
- package/dist/tools/property-dictionary.d.ts +13 -0
- package/dist/tools/property-dictionary.js +82 -0
- package/dist/tools/sequence.d.ts +73 -48
- package/dist/tools/sequence.js +196 -748
- 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 +66 -34
- package/dist/tools/ui.js +134 -214
- package/dist/types/env.d.ts +0 -3
- package/dist/types/env.js +0 -7
- 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 +67 -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/response-factory.d.ts +7 -0
- package/dist/utils/response-factory.js +33 -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 +692 -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 +60 -27
- 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 +131 -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 +57 -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 +12 -0
- package/src/graphql/resolvers.ts +1010 -0
- package/src/graphql/schema.ts +452 -0
- package/src/graphql/server.ts +154 -0
- package/src/graphql/types.ts +7 -0
- package/src/handlers/resource-handlers.ts +186 -0
- package/src/index.ts +152 -663
- package/src/prompts/index.ts +4 -4
- package/src/resources/actors.ts +58 -76
- package/src/resources/assets.ts +147 -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 +148 -0
- package/src/services/health-monitor.ts +132 -0
- package/src/services/metrics-server.ts +142 -0
- package/src/tools/actors.ts +417 -322
- package/src/tools/animation.ts +671 -461
- package/src/tools/assets.ts +353 -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/helpers.ts +189 -0
- package/src/tools/blueprint.ts +787 -965
- package/src/tools/consolidated-tool-definitions.ts +993 -515
- package/src/tools/consolidated-tool-handlers.ts +272 -1139
- package/src/tools/debug.ts +292 -187
- package/src/tools/dynamic-handler-registry.ts +151 -0
- package/src/tools/editor.ts +309 -246
- package/src/tools/engine.ts +14 -3
- package/src/tools/environment.ts +287 -0
- package/src/tools/foliage.ts +314 -379
- package/src/tools/handlers/actor-handlers.ts +271 -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 +394 -489
- package/src/tools/level.ts +752 -694
- package/src/tools/lighting.ts +583 -984
- package/src/tools/logs.ts +9 -57
- package/src/tools/materials.ts +231 -121
- package/src/tools/niagara.ts +293 -168
- package/src/tools/performance.ts +320 -168
- package/src/tools/physics.ts +268 -613
- package/src/tools/property-dictionary.ts +98 -0
- package/src/tools/sequence.ts +255 -815
- package/src/tools/tool-definition-utils.ts +35 -0
- package/src/tools/ui.ts +207 -283
- package/src/types/env.ts +0 -10
- 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 +75 -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.ts +60 -0
- package/src/utils/response-factory.ts +39 -0
- package/src/utils/response-validator.ts +176 -56
- package/src/utils/result-helpers.ts +21 -19
- package/src/utils/safe-json.ts +14 -11
- package/src/utils/unreal-command-queue.ts +152 -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 +44 -0
- package/tests/test-asset-advanced.mjs +82 -0
- package/tests/test-asset-errors.mjs +35 -0
- package/tests/test-audio.mjs +219 -0
- package/tests/test-automation-timeouts.mjs +98 -0
- package/tests/test-behavior-tree.mjs +261 -0
- package/tests/test-blueprint-events.mjs +35 -0
- package/tests/test-blueprint-graph.mjs +79 -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 +80 -0
- package/tests/test-extra-tools.mjs +38 -0
- package/tests/test-graphql.mjs +322 -0
- package/tests/test-inspect.mjs +72 -0
- package/tests/test-landscape.mjs +60 -0
- package/tests/test-manage-asset.mjs +438 -0
- package/tests/test-manage-level.mjs +70 -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-plugin-handshake.mjs +82 -0
- package/tests/test-render.mjs +33 -0
- package/tests/test-runner.mjs +933 -0
- package/tests/test-search-assets.mjs +66 -0
- package/tests/test-sequence.mjs +68 -0
- package/tests/test-system.mjs +57 -0
- package/tests/test-wasm.mjs +193 -0
- package/tests/test-world-partition.mjs +215 -0
- package/tsconfig.json +3 -3
- 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/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/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
package/src/prompts/index.ts
CHANGED
|
@@ -16,20 +16,20 @@ export interface PromptTemplate {
|
|
|
16
16
|
}>;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
function clampChoice(value: unknown, choices: string[],
|
|
19
|
+
function clampChoice(value: unknown, choices: string[], defaultChoice: string): string {
|
|
20
20
|
if (typeof value === 'string') {
|
|
21
21
|
const normalized = value.toLowerCase();
|
|
22
22
|
if (choices.includes(normalized)) {
|
|
23
23
|
return normalized;
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
return
|
|
26
|
+
return defaultChoice;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
function coerceNumber(value: unknown,
|
|
29
|
+
function coerceNumber(value: unknown, defaultValue: number, min?: number, max?: number): number {
|
|
30
30
|
const num = typeof value === 'number' ? value : Number(value);
|
|
31
31
|
if (!Number.isFinite(num)) {
|
|
32
|
-
return
|
|
32
|
+
return defaultValue;
|
|
33
33
|
}
|
|
34
34
|
if (min !== undefined && num < min) {
|
|
35
35
|
return min;
|
package/src/resources/actors.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { UnrealBridge } from '../unreal-bridge.js';
|
|
2
|
-
import {
|
|
2
|
+
import { coerceNumber, coerceString } from '../utils/result-helpers.js';
|
|
3
3
|
|
|
4
4
|
interface CacheEntry {
|
|
5
5
|
data: any;
|
|
@@ -9,8 +9,11 @@ interface CacheEntry {
|
|
|
9
9
|
export class ActorResources {
|
|
10
10
|
private cache = new Map<string, CacheEntry>();
|
|
11
11
|
private readonly CACHE_TTL_MS = 5000; // 5 seconds cache for actors (they change more frequently)
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
private automationBridgeAvailable = false;
|
|
13
|
+
|
|
14
|
+
constructor(private bridge: UnrealBridge, private automationBridge?: any) {
|
|
15
|
+
this.automationBridgeAvailable = Boolean(automationBridge && typeof automationBridge.sendAutomationRequest === 'function');
|
|
16
|
+
}
|
|
14
17
|
|
|
15
18
|
private getFromCache(key: string): any | null {
|
|
16
19
|
const entry = this.cache.get(key);
|
|
@@ -32,114 +35,93 @@ export class ActorResources {
|
|
|
32
35
|
return cached;
|
|
33
36
|
}
|
|
34
37
|
|
|
35
|
-
// Use Python to get actors via EditorActorSubsystem
|
|
36
38
|
try {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
actors = actor_subsystem.get_all_level_actors() if actor_subsystem else []
|
|
41
|
-
actor_list = []
|
|
42
|
-
for actor in actors:
|
|
43
|
-
try:
|
|
44
|
-
if actor:
|
|
45
|
-
actor_list.append({
|
|
46
|
-
'name': actor.get_name(),
|
|
47
|
-
'class': actor.get_class().get_name(),
|
|
48
|
-
'path': actor.get_path_name()
|
|
49
|
-
})
|
|
50
|
-
except Exception:
|
|
51
|
-
pass
|
|
52
|
-
print('RESULT:' + json.dumps({'success': True, 'count': len(actor_list), 'actors': actor_list}))
|
|
53
|
-
`.trim();
|
|
54
|
-
|
|
55
|
-
const response = await this.bridge.executePython(pythonCode);
|
|
56
|
-
const interpreted = interpretStandardResult(response, {
|
|
57
|
-
successMessage: 'Retrieved actor list',
|
|
58
|
-
failureMessage: 'Failed to retrieve actor list'
|
|
59
|
-
});
|
|
39
|
+
if (!this.automationBridgeAvailable) {
|
|
40
|
+
return { success: false, error: 'Automation bridge is not available. Please ensure Unreal Engine is running with the MCP Automation Bridge plugin.' };
|
|
41
|
+
}
|
|
60
42
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
count,
|
|
67
|
-
actors
|
|
68
|
-
};
|
|
43
|
+
const resp: any = await this.automationBridge.sendAutomationRequest('control_actor', { action: 'list' });
|
|
44
|
+
if (resp && resp.success !== false && Array.isArray((resp.result || resp).actors)) {
|
|
45
|
+
const actors = (resp.result || resp).actors as any[];
|
|
46
|
+
const count = coerceNumber((resp.result || resp).count) ?? actors.length;
|
|
47
|
+
const payload = { success: true as const, count, actors };
|
|
69
48
|
this.setCache('listActors', payload);
|
|
70
49
|
return payload;
|
|
71
50
|
}
|
|
72
51
|
|
|
73
|
-
return {
|
|
74
|
-
success: false,
|
|
75
|
-
error: coerceString(interpreted.payload.error) ?? interpreted.error ?? 'Failed to parse actors list',
|
|
76
|
-
note: bestEffortInterpretedText(interpreted)
|
|
77
|
-
};
|
|
52
|
+
return { success: false, error: 'Failed to retrieve actor list from automation bridge' };
|
|
78
53
|
} catch (err) {
|
|
79
54
|
return { success: false, error: `Failed to list actors: ${err}` };
|
|
80
55
|
}
|
|
81
56
|
}
|
|
82
57
|
|
|
83
58
|
async getActorByName(actorName: string) {
|
|
84
|
-
// GetActorOfClass expects a class, not a name. Use Python to find by name
|
|
85
59
|
try {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
actor_subsystem = unreal.get_editor_subsystem(unreal.EditorActorSubsystem)
|
|
91
|
-
actors = actor_subsystem.get_all_level_actors() if actor_subsystem else []
|
|
92
|
-
|
|
93
|
-
found = None
|
|
94
|
-
for actor in actors:
|
|
95
|
-
if actor and actor.get_name() == ${JSON.stringify(actorName)}:
|
|
96
|
-
found = {
|
|
97
|
-
'success': True,
|
|
98
|
-
'name': actor.get_name(),
|
|
99
|
-
'path': actor.get_path_name(),
|
|
100
|
-
'class': actor.get_class().get_name()
|
|
101
|
-
}
|
|
102
|
-
break
|
|
103
|
-
|
|
104
|
-
if not found:
|
|
105
|
-
found = {'success': False, 'error': f"Actor not found: {actorName}"}
|
|
106
|
-
|
|
107
|
-
print('RESULT:' + json.dumps(found))
|
|
108
|
-
`.trim();
|
|
60
|
+
if (!this.automationBridgeAvailable) {
|
|
61
|
+
return { success: false, error: 'Automation bridge is not available' };
|
|
62
|
+
}
|
|
109
63
|
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
failureMessage: `Actor not found: ${actorName}`
|
|
64
|
+
const resp: any = await this.automationBridge.sendAutomationRequest('control_actor', {
|
|
65
|
+
action: 'find_by_name',
|
|
66
|
+
name: actorName
|
|
114
67
|
});
|
|
115
68
|
|
|
116
|
-
if (
|
|
69
|
+
if (resp && resp.success !== false && resp.result) {
|
|
117
70
|
return {
|
|
118
71
|
success: true as const,
|
|
119
|
-
name: coerceString(
|
|
120
|
-
path: coerceString(
|
|
121
|
-
class: coerceString(
|
|
72
|
+
name: coerceString(resp.result.name) ?? actorName,
|
|
73
|
+
path: coerceString(resp.result.path),
|
|
74
|
+
class: coerceString(resp.result.class)
|
|
122
75
|
};
|
|
123
76
|
}
|
|
124
77
|
|
|
125
78
|
return {
|
|
126
79
|
success: false as const,
|
|
127
|
-
error:
|
|
80
|
+
error: `Actor not found: ${actorName}`
|
|
128
81
|
};
|
|
129
82
|
} catch (err) {
|
|
130
|
-
return { error: `Failed to get actor: ${err}` };
|
|
83
|
+
return { success: false, error: `Failed to get actor: ${err}` };
|
|
131
84
|
}
|
|
132
85
|
}
|
|
133
86
|
|
|
134
87
|
async getActorTransform(actorPath: string) {
|
|
135
88
|
try {
|
|
136
|
-
|
|
89
|
+
return await this.bridge.getObjectProperty({
|
|
137
90
|
objectPath: actorPath,
|
|
138
91
|
propertyName: 'ActorTransform'
|
|
139
92
|
});
|
|
140
|
-
return res;
|
|
141
93
|
} catch (err) {
|
|
142
94
|
return { error: `Failed to get transform: ${err}` };
|
|
143
95
|
}
|
|
144
96
|
}
|
|
97
|
+
|
|
98
|
+
async listActorComponents(actorPath: string) {
|
|
99
|
+
try {
|
|
100
|
+
if (!this.automationBridgeAvailable) {
|
|
101
|
+
return { success: false, error: 'Automation bridge is not available' };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const resp: any = await this.automationBridge.sendAutomationRequest('control_actor', {
|
|
105
|
+
action: 'list_components',
|
|
106
|
+
actor_path: actorPath
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
if (resp && resp.success !== false && Array.isArray(resp.result?.components)) {
|
|
110
|
+
return {
|
|
111
|
+
success: true as const,
|
|
112
|
+
components: resp.result.components
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
success: false as const,
|
|
118
|
+
error: `Failed to resolve components for ${actorPath}`
|
|
119
|
+
};
|
|
120
|
+
} catch (err) {
|
|
121
|
+
return {
|
|
122
|
+
success: false as const,
|
|
123
|
+
error: `Component lookup failed: ${err}`
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
145
127
|
}
|
package/src/resources/assets.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
export class AssetResources {
|
|
5
|
-
constructor(private bridge: UnrealBridge) {}
|
|
1
|
+
import { BaseTool } from '../tools/base-tool.js';
|
|
2
|
+
import { IAssetResources } from '../types/tool-interfaces.js';
|
|
3
|
+
import { coerceString } from '../utils/result-helpers.js';
|
|
6
4
|
|
|
5
|
+
export class AssetResources extends BaseTool implements IAssetResources {
|
|
7
6
|
// Simple in-memory cache for asset listing
|
|
8
7
|
private cache = new Map<string, { timestamp: number; data: any }>();
|
|
9
8
|
private get ttlMs(): number { return Number(process.env.ASSET_LIST_TTL_MS || 10000); }
|
|
10
|
-
private makeKey(dir: string, recursive: boolean, page?: number) {
|
|
11
|
-
return page !== undefined ? `${dir}::${recursive ? 1 : 0}::${page}` : `${dir}::${recursive ? 1 : 0}`;
|
|
9
|
+
private makeKey(dir: string, recursive: boolean, page?: number) {
|
|
10
|
+
return page !== undefined ? `${dir}::${recursive ? 1 : 0}::${page}` : `${dir}::${recursive ? 1 : 0}`;
|
|
12
11
|
}
|
|
13
12
|
|
|
14
13
|
// Normalize UE content paths:
|
|
@@ -32,11 +31,48 @@ export class AssetResources {
|
|
|
32
31
|
}
|
|
33
32
|
}
|
|
34
33
|
|
|
34
|
+
clearCache(dir?: string) {
|
|
35
|
+
if (!dir) {
|
|
36
|
+
this.cache.clear();
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const normalized = this.normalizeDir(dir);
|
|
41
|
+
for (const key of Array.from(this.cache.keys())) {
|
|
42
|
+
if (key.startsWith(`${normalized}::`)) {
|
|
43
|
+
this.cache.delete(key);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
invalidateAssetPaths(paths: string[]) {
|
|
49
|
+
if (!Array.isArray(paths) || paths.length === 0) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const dirs = new Set<string>();
|
|
54
|
+
for (const rawPath of paths) {
|
|
55
|
+
if (typeof rawPath !== 'string' || rawPath.trim().length === 0) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const normalized = this.normalizeDir(rawPath);
|
|
59
|
+
dirs.add(normalized);
|
|
60
|
+
const parent = this.parentDirectory(normalized);
|
|
61
|
+
if (parent) {
|
|
62
|
+
dirs.add(parent);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
for (const dir of dirs) {
|
|
67
|
+
this.clearCache(dir);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
35
71
|
async list(dir = '/Game', _recursive = false, limit = 50) {
|
|
36
72
|
// ALWAYS use non-recursive listing to show only immediate children
|
|
37
73
|
// This prevents timeouts and makes navigation clearer
|
|
38
74
|
_recursive = false; // Force non-recursive
|
|
39
|
-
|
|
75
|
+
|
|
40
76
|
// Normalize directory first
|
|
41
77
|
dir = this.normalizeDir(dir);
|
|
42
78
|
|
|
@@ -46,22 +82,24 @@ export class AssetResources {
|
|
|
46
82
|
const entry = this.cache.get(key);
|
|
47
83
|
const now = Date.now();
|
|
48
84
|
if (entry && (now - entry.timestamp) < this.ttlMs) {
|
|
49
|
-
return entry.data;
|
|
85
|
+
return { success: true, ...entry.data };
|
|
50
86
|
}
|
|
51
|
-
} catch {}
|
|
52
|
-
|
|
87
|
+
} catch { }
|
|
88
|
+
|
|
53
89
|
// Check if bridge is connected
|
|
54
90
|
if (!this.bridge.isConnected) {
|
|
55
91
|
return {
|
|
92
|
+
success: false,
|
|
56
93
|
assets: [],
|
|
57
|
-
warning: 'Unreal Engine is not connected. Please ensure Unreal Engine is running with
|
|
94
|
+
warning: 'Unreal Engine is not connected. Please ensure Unreal Engine is running with the MCP server enabled.',
|
|
58
95
|
connectionStatus: 'disconnected'
|
|
59
96
|
};
|
|
60
97
|
}
|
|
61
|
-
|
|
98
|
+
|
|
62
99
|
// Always use directory-only listing (immediate children)
|
|
63
|
-
|
|
64
|
-
//
|
|
100
|
+
const listed = await this.listDirectoryOnly(dir, false, limit);
|
|
101
|
+
// Ensure a success flag is present so downstream evaluators don't assume success implicitly
|
|
102
|
+
return { ...listed, success: listed && (listed as any).success === false ? false : true };
|
|
65
103
|
}
|
|
66
104
|
|
|
67
105
|
/**
|
|
@@ -74,7 +112,7 @@ export class AssetResources {
|
|
|
74
112
|
// Ensure pageSize doesn't exceed safe limit
|
|
75
113
|
const safePageSize = Math.min(pageSize, 50);
|
|
76
114
|
const offset = page * safePageSize;
|
|
77
|
-
|
|
115
|
+
|
|
78
116
|
// Normalize directory and check cache for this specific page
|
|
79
117
|
dir = this.normalizeDir(dir);
|
|
80
118
|
const cacheKey = this.makeKey(dir, recursive, page);
|
|
@@ -82,7 +120,7 @@ export class AssetResources {
|
|
|
82
120
|
if (cached && (Date.now() - cached.timestamp) < this.ttlMs) {
|
|
83
121
|
return cached.data;
|
|
84
122
|
}
|
|
85
|
-
|
|
123
|
+
|
|
86
124
|
if (!this.bridge.isConnected) {
|
|
87
125
|
return {
|
|
88
126
|
assets: [],
|
|
@@ -92,17 +130,17 @@ export class AssetResources {
|
|
|
92
130
|
connectionStatus: 'disconnected'
|
|
93
131
|
};
|
|
94
132
|
}
|
|
95
|
-
|
|
133
|
+
|
|
96
134
|
try {
|
|
97
135
|
// Use search API with pagination
|
|
98
136
|
// Use the same directory listing approach but with pagination
|
|
99
137
|
const allAssets = await this.listDirectoryOnly(dir, false, 1000);
|
|
100
|
-
|
|
138
|
+
|
|
101
139
|
// Paginate the results
|
|
102
140
|
const start = offset;
|
|
103
141
|
const end = offset + safePageSize;
|
|
104
142
|
const pagedAssets = allAssets.assets ? allAssets.assets.slice(start, end) : [];
|
|
105
|
-
|
|
143
|
+
|
|
106
144
|
const result = {
|
|
107
145
|
assets: pagedAssets,
|
|
108
146
|
page,
|
|
@@ -112,13 +150,13 @@ export class AssetResources {
|
|
|
112
150
|
hasMore: end < (allAssets.assets ? allAssets.assets.length : 0),
|
|
113
151
|
method: 'directory_listing_paged'
|
|
114
152
|
};
|
|
115
|
-
|
|
153
|
+
|
|
116
154
|
this.cache.set(cacheKey, { timestamp: Date.now(), data: result });
|
|
117
155
|
return result;
|
|
118
156
|
} catch (err: any) {
|
|
119
157
|
console.warn(`Asset listing page ${page} failed:`, err.message);
|
|
120
158
|
}
|
|
121
|
-
|
|
159
|
+
|
|
122
160
|
return {
|
|
123
161
|
assets: [],
|
|
124
162
|
page,
|
|
@@ -134,109 +172,80 @@ export class AssetResources {
|
|
|
134
172
|
private async listDirectoryOnly(dir: string, _recursive: boolean, limit: number) {
|
|
135
173
|
// Always return only immediate children to avoid timeout and improve navigation
|
|
136
174
|
try {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
pass
|
|
154
|
-
|
|
155
|
-
# Immediate assets at this path
|
|
156
|
-
assets_data = ar.get_assets_by_path(_dir, False)
|
|
157
|
-
assets = []
|
|
158
|
-
for a in assets_data[:${limit}]:
|
|
159
|
-
try:
|
|
160
|
-
assets.append({
|
|
161
|
-
'n': str(a.asset_name),
|
|
162
|
-
'p': str(a.object_path),
|
|
163
|
-
'c': str(a.asset_class)
|
|
164
|
-
})
|
|
165
|
-
except Exception:
|
|
166
|
-
pass
|
|
167
|
-
|
|
168
|
-
print("RESULT:" + json.dumps({
|
|
169
|
-
'success': True,
|
|
170
|
-
'path': _dir,
|
|
171
|
-
'folders': len(folders_list),
|
|
172
|
-
'files': len(assets),
|
|
173
|
-
'folders_list': folders_list,
|
|
174
|
-
'assets': assets
|
|
175
|
-
}))
|
|
176
|
-
except Exception as e:
|
|
177
|
-
print("RESULT:" + json.dumps({'success': False, 'error': str(e), 'path': _dir}))
|
|
178
|
-
`.trim();
|
|
179
|
-
|
|
180
|
-
const resp = await this.bridge.executePython(py);
|
|
181
|
-
const interpreted = interpretStandardResult(resp, {
|
|
182
|
-
successMessage: 'Directory contents retrieved',
|
|
183
|
-
failureMessage: 'Failed to list directory contents'
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
if (interpreted.success) {
|
|
187
|
-
const payload = interpreted.payload as Record<string, unknown>;
|
|
188
|
-
|
|
189
|
-
const foldersArr = Array.isArray(payload.folders_list)
|
|
190
|
-
? payload.folders_list.map((f: any) => ({
|
|
191
|
-
Name: coerceString(f?.n) ?? '',
|
|
192
|
-
Path: coerceString(f?.p) ?? '',
|
|
175
|
+
// Use the native C++ plugin's list action instead of Python
|
|
176
|
+
try {
|
|
177
|
+
const normalizedDir = this.normalizeDir(dir);
|
|
178
|
+
const response = await this.sendAutomationRequest(
|
|
179
|
+
'list',
|
|
180
|
+
{ directory: normalizedDir, limit, recursive: false },
|
|
181
|
+
{ timeoutMs: 30000 }
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
if (response.success !== false && response.result) {
|
|
185
|
+
const payload = response.result;
|
|
186
|
+
|
|
187
|
+
const foldersArr = Array.isArray(payload.folders_list)
|
|
188
|
+
? payload.folders_list.map((f: any) => ({
|
|
189
|
+
Name: coerceString(f?.n ?? f?.Name ?? f?.name) ?? '',
|
|
190
|
+
Path: coerceString(f?.p ?? f?.Path ?? f?.path) ?? '',
|
|
193
191
|
Class: 'Folder',
|
|
194
192
|
isFolder: true
|
|
195
193
|
}))
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
Name: coerceString(a?.n) ?? '',
|
|
201
|
-
Path: coerceString(a?.p) ?? '',
|
|
202
|
-
Class: coerceString(a?.c) ?? '
|
|
203
|
-
isFolder: false
|
|
194
|
+
: [];
|
|
195
|
+
|
|
196
|
+
const assetsArr = Array.isArray(payload.assets)
|
|
197
|
+
? payload.assets.map((a: any) => ({
|
|
198
|
+
Name: coerceString(a?.n ?? a?.Name ?? a?.name) ?? '',
|
|
199
|
+
Path: coerceString(a?.p ?? a?.Path ?? a?.path) ?? '',
|
|
200
|
+
Class: coerceString(a?.c ?? a?.Class ?? a?.class) ?? 'Object'
|
|
204
201
|
}))
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
202
|
+
: [];
|
|
203
|
+
|
|
204
|
+
const result = {
|
|
205
|
+
success: true,
|
|
206
|
+
assets: [...foldersArr, ...assetsArr],
|
|
207
|
+
count: foldersArr.length + assetsArr.length,
|
|
208
|
+
folders: foldersArr.length,
|
|
209
|
+
files: assetsArr.length,
|
|
210
|
+
path: normalizedDir,
|
|
211
|
+
recursive: false,
|
|
212
|
+
method: 'automation_bridge',
|
|
213
|
+
cached: false
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const key = this.makeKey(dir, false);
|
|
217
|
+
this.cache.set(key, { timestamp: Date.now(), data: result });
|
|
218
|
+
return result;
|
|
219
|
+
}
|
|
220
|
+
} catch { }
|
|
221
|
+
|
|
222
|
+
// No fallback available
|
|
227
223
|
} catch (err: any) {
|
|
228
|
-
|
|
224
|
+
const errorMessage = err?.message ? String(err.message) : 'Asset registry request failed';
|
|
225
|
+
console.warn('Engine asset listing failed:', errorMessage);
|
|
226
|
+
return {
|
|
227
|
+
success: false,
|
|
228
|
+
path: this.normalizeDir(dir),
|
|
229
|
+
summary: { total: 0, folders: 0, assets: 0 },
|
|
230
|
+
foldersList: [],
|
|
231
|
+
assets: [],
|
|
232
|
+
error: errorMessage,
|
|
233
|
+
warning: 'AssetRegistry query failed. Ensure the MCP Automation Bridge is connected.',
|
|
234
|
+
transport: 'automation_bridge',
|
|
235
|
+
method: 'asset_registry_alternate'
|
|
236
|
+
};
|
|
229
237
|
}
|
|
230
|
-
|
|
231
|
-
// Fallback: return empty with explanation
|
|
238
|
+
|
|
232
239
|
return {
|
|
233
|
-
success:
|
|
240
|
+
success: false,
|
|
234
241
|
path: this.normalizeDir(dir),
|
|
235
242
|
summary: { total: 0, folders: 0, assets: 0 },
|
|
236
243
|
foldersList: [],
|
|
237
244
|
assets: [],
|
|
238
|
-
|
|
239
|
-
|
|
245
|
+
error: 'Asset registry returned no payload.',
|
|
246
|
+
warning: 'No items returned from AssetRegistry request.',
|
|
247
|
+
transport: 'automation_bridge',
|
|
248
|
+
method: 'asset_registry_empty'
|
|
240
249
|
};
|
|
241
250
|
}
|
|
242
251
|
|
|
@@ -246,27 +255,31 @@ except Exception as e:
|
|
|
246
255
|
return false;
|
|
247
256
|
}
|
|
248
257
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
258
|
+
try {
|
|
259
|
+
const normalizedPath = this.normalizeDir(assetPath);
|
|
260
|
+
const response = await this.sendAutomationRequest(
|
|
261
|
+
'asset_exists',
|
|
262
|
+
{ asset_path: normalizedPath }
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
return response?.success !== false && response?.result?.exists === true;
|
|
266
|
+
} catch {
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
private parentDirectory(path: string): string | null {
|
|
272
|
+
if (!path || typeof path !== 'string') {
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const normalized = this.normalizeDir(path);
|
|
277
|
+
const lastSlash = normalized.lastIndexOf('/');
|
|
278
|
+
if (lastSlash <= 0) {
|
|
279
|
+
return normalized === '/' ? '/' : null;
|
|
268
280
|
}
|
|
269
281
|
|
|
270
|
-
|
|
282
|
+
const parent = normalized.substring(0, lastSlash);
|
|
283
|
+
return parent.length > 0 ? parent : '/';
|
|
271
284
|
}
|
|
272
285
|
}
|