unreal-engine-mcp-server 0.5.4 → 0.5.5
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/dist/automation/bridge.d.ts.map +1 -0
- package/dist/automation/bridge.js.map +1 -0
- package/dist/automation/connection-manager.d.ts.map +1 -0
- package/dist/automation/connection-manager.js.map +1 -0
- package/dist/automation/handshake.d.ts.map +1 -0
- package/dist/automation/handshake.js.map +1 -0
- package/dist/automation/index.d.ts.map +1 -0
- package/dist/automation/index.js.map +1 -0
- package/dist/automation/message-handler.d.ts.map +1 -0
- package/dist/automation/message-handler.js.map +1 -0
- package/dist/automation/request-tracker.d.ts.map +1 -0
- package/dist/automation/request-tracker.js.map +1 -0
- package/dist/automation/types.d.ts.map +1 -0
- package/dist/automation/types.js.map +1 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +4 -3
- package/dist/cli.js.map +1 -0
- package/dist/config/class-aliases.d.ts.map +1 -0
- package/dist/config/class-aliases.js.map +1 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js.map +1 -0
- package/dist/graphql/loaders.d.ts.map +1 -0
- package/dist/graphql/loaders.js.map +1 -0
- package/dist/graphql/resolvers.d.ts.map +1 -0
- package/dist/graphql/resolvers.js +29 -29
- package/dist/graphql/resolvers.js.map +1 -0
- package/dist/graphql/schema.d.ts.map +1 -0
- package/dist/graphql/schema.js.map +1 -0
- package/dist/graphql/server.d.ts.map +1 -0
- package/dist/graphql/server.js.map +1 -0
- package/dist/graphql/types.d.ts.map +1 -0
- package/dist/graphql/types.js.map +1 -0
- package/dist/handlers/resource-handlers.d.ts.map +1 -0
- package/dist/handlers/resource-handlers.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +64 -7
- package/dist/index.js.map +1 -0
- package/dist/resources/actors.d.ts.map +1 -0
- package/dist/resources/actors.js.map +1 -0
- package/dist/resources/assets.d.ts.map +1 -0
- package/dist/resources/assets.js +6 -4
- package/dist/resources/assets.js.map +1 -0
- package/dist/resources/levels.d.ts.map +1 -0
- package/dist/resources/levels.js.map +1 -0
- package/dist/server/resource-registry.d.ts.map +1 -0
- package/dist/server/resource-registry.js.map +1 -0
- package/dist/server/tool-registry.d.ts.map +1 -0
- package/dist/server/tool-registry.js.map +1 -0
- package/dist/server-setup.d.ts.map +1 -0
- package/dist/server-setup.js.map +1 -0
- package/dist/services/health-monitor.d.ts.map +1 -0
- package/dist/services/health-monitor.js.map +1 -0
- package/dist/services/metrics-server.d.ts.map +1 -0
- package/dist/services/metrics-server.js.map +1 -0
- package/dist/tools/actors.d.ts.map +1 -0
- package/dist/tools/actors.js +3 -1
- package/dist/tools/actors.js.map +1 -0
- package/dist/tools/animation.d.ts.map +1 -0
- package/dist/tools/animation.js +2 -2
- package/dist/tools/animation.js.map +1 -0
- package/dist/tools/assets.d.ts.map +1 -0
- package/dist/tools/assets.js.map +1 -0
- package/dist/tools/audio.d.ts.map +1 -0
- package/dist/tools/audio.js.map +1 -0
- package/dist/tools/base-tool.d.ts.map +1 -0
- package/dist/tools/base-tool.js.map +1 -0
- package/dist/tools/behavior-tree.d.ts.map +1 -0
- package/dist/tools/behavior-tree.js.map +1 -0
- package/dist/tools/blueprint.d.ts.map +1 -0
- package/dist/tools/blueprint.js +4 -2
- package/dist/tools/blueprint.js.map +1 -0
- package/dist/tools/consolidated-tool-definitions.d.ts.map +1 -0
- package/dist/tools/consolidated-tool-definitions.js.map +1 -0
- package/dist/tools/consolidated-tool-handlers.d.ts.map +1 -0
- package/dist/tools/consolidated-tool-handlers.js.map +1 -0
- package/dist/tools/debug.d.ts.map +1 -0
- package/dist/tools/debug.js +3 -1
- package/dist/tools/debug.js.map +1 -0
- package/dist/tools/dynamic-handler-registry.d.ts.map +1 -0
- package/dist/tools/dynamic-handler-registry.js +3 -1
- package/dist/tools/dynamic-handler-registry.js.map +1 -0
- package/dist/tools/editor.d.ts.map +1 -0
- package/dist/tools/editor.js +1 -1
- package/dist/tools/editor.js.map +1 -0
- package/dist/tools/engine.d.ts.map +1 -0
- package/dist/tools/engine.js.map +1 -0
- package/dist/tools/environment.d.ts.map +1 -0
- package/dist/tools/environment.js +2 -2
- package/dist/tools/environment.js.map +1 -0
- package/dist/tools/foliage.d.ts.map +1 -0
- package/dist/tools/foliage.js.map +1 -0
- package/dist/tools/handlers/actor-handlers.d.ts +1 -1
- package/dist/tools/handlers/actor-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/actor-handlers.js +6 -5
- package/dist/tools/handlers/actor-handlers.js.map +1 -0
- package/dist/tools/handlers/animation-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/animation-handlers.js.map +1 -0
- package/dist/tools/handlers/argument-helper.d.ts.map +1 -0
- package/dist/tools/handlers/argument-helper.js.map +1 -0
- package/dist/tools/handlers/asset-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/asset-handlers.js +5 -1
- package/dist/tools/handlers/asset-handlers.js.map +1 -0
- package/dist/tools/handlers/audio-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/audio-handlers.js.map +1 -0
- package/dist/tools/handlers/blueprint-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/blueprint-handlers.js +2 -1
- package/dist/tools/handlers/blueprint-handlers.js.map +1 -0
- package/dist/tools/handlers/common-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/common-handlers.js.map +1 -0
- package/dist/tools/handlers/editor-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/editor-handlers.js +12 -2
- package/dist/tools/handlers/editor-handlers.js.map +1 -0
- package/dist/tools/handlers/effect-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/effect-handlers.js.map +1 -0
- package/dist/tools/handlers/environment-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/environment-handlers.js.map +1 -0
- package/dist/tools/handlers/graph-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/graph-handlers.js +61 -1
- package/dist/tools/handlers/graph-handlers.js.map +1 -0
- package/dist/tools/handlers/input-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/input-handlers.js.map +1 -0
- package/dist/tools/handlers/inspect-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/inspect-handlers.js.map +1 -0
- package/dist/tools/handlers/level-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/level-handlers.js.map +1 -0
- package/dist/tools/handlers/lighting-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/lighting-handlers.js +23 -1
- package/dist/tools/handlers/lighting-handlers.js.map +1 -0
- package/dist/tools/handlers/performance-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/performance-handlers.js +15 -2
- package/dist/tools/handlers/performance-handlers.js.map +1 -0
- package/dist/tools/handlers/pipeline-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/pipeline-handlers.js.map +1 -0
- package/dist/tools/handlers/sequence-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/sequence-handlers.js.map +1 -0
- package/dist/tools/handlers/system-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/system-handlers.js +16 -1
- package/dist/tools/handlers/system-handlers.js.map +1 -0
- package/dist/tools/input.d.ts.map +1 -0
- package/dist/tools/input.js +3 -1
- package/dist/tools/input.js.map +1 -0
- package/dist/tools/introspection.d.ts.map +1 -0
- package/dist/tools/introspection.js.map +1 -0
- package/dist/tools/landscape.d.ts.map +1 -0
- package/dist/tools/landscape.js +3 -1
- package/dist/tools/landscape.js.map +1 -0
- package/dist/tools/level.d.ts.map +1 -0
- package/dist/tools/level.js.map +1 -0
- package/dist/tools/lighting.d.ts.map +1 -0
- package/dist/tools/lighting.js +3 -1
- package/dist/tools/lighting.js.map +1 -0
- package/dist/tools/logs.d.ts.map +1 -0
- package/dist/tools/logs.js.map +1 -0
- package/dist/tools/materials.d.ts.map +1 -0
- package/dist/tools/materials.js +3 -1
- package/dist/tools/materials.js.map +1 -0
- package/dist/tools/niagara.d.ts.map +1 -0
- package/dist/tools/niagara.js +7 -5
- package/dist/tools/niagara.js.map +1 -0
- package/dist/tools/performance.d.ts.map +1 -0
- package/dist/tools/performance.js.map +1 -0
- package/dist/tools/physics.d.ts.map +1 -0
- package/dist/tools/physics.js +9 -7
- package/dist/tools/physics.js.map +1 -0
- package/dist/tools/property-dictionary.d.ts.map +1 -0
- package/dist/tools/property-dictionary.js.map +1 -0
- package/dist/tools/sequence.d.ts.map +1 -0
- package/dist/tools/sequence.js +3 -1
- package/dist/tools/sequence.js.map +1 -0
- package/dist/tools/tool-definition-utils.d.ts.map +1 -0
- package/dist/tools/tool-definition-utils.js.map +1 -0
- package/dist/tools/ui.d.ts.map +1 -0
- package/dist/tools/ui.js +3 -1
- package/dist/tools/ui.js.map +1 -0
- package/dist/types/automation-responses.d.ts.map +1 -0
- package/dist/types/automation-responses.js.map +1 -0
- package/dist/types/env.d.ts.map +1 -0
- package/dist/types/env.js.map +1 -0
- package/dist/types/handler-types.d.ts.map +1 -0
- package/dist/types/handler-types.js.map +1 -0
- package/dist/types/tool-interfaces.d.ts.map +1 -0
- package/dist/types/tool-interfaces.js.map +1 -0
- package/dist/types/tool-types.d.ts.map +1 -0
- package/dist/types/tool-types.js.map +1 -0
- package/dist/unreal-bridge.d.ts +1 -0
- package/dist/unreal-bridge.d.ts.map +1 -0
- package/dist/unreal-bridge.js +8 -0
- package/dist/unreal-bridge.js.map +1 -0
- package/dist/utils/command-validator.d.ts.map +1 -0
- package/dist/utils/command-validator.js.map +1 -0
- package/dist/utils/elicitation.d.ts.map +1 -0
- package/dist/utils/elicitation.js.map +1 -0
- package/dist/utils/error-handler.d.ts.map +1 -0
- package/dist/utils/error-handler.js.map +1 -0
- package/dist/utils/ini-reader.d.ts.map +1 -0
- package/dist/utils/ini-reader.js.map +1 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/normalize.d.ts.map +1 -0
- package/dist/utils/normalize.js.map +1 -0
- package/dist/utils/path-security.d.ts.map +1 -0
- package/dist/utils/path-security.js.map +1 -0
- package/dist/utils/response-factory.d.ts.map +1 -0
- package/dist/utils/response-factory.js +3 -1
- package/dist/utils/response-factory.js.map +1 -0
- package/dist/utils/response-validator.d.ts.map +1 -0
- package/dist/utils/response-validator.js.map +1 -0
- package/dist/utils/result-helpers.d.ts.map +1 -0
- package/dist/utils/result-helpers.js.map +1 -0
- package/dist/utils/safe-json.d.ts.map +1 -0
- package/dist/utils/safe-json.js.map +1 -0
- package/dist/utils/unreal-command-queue.d.ts.map +1 -0
- package/dist/utils/unreal-command-queue.js.map +1 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js.map +1 -0
- package/dist/wasm/index.d.ts.map +1 -0
- package/dist/wasm/index.js.map +1 -0
- package/package.json +12 -34
- package/server.json +2 -2
- package/.dockerignore +0 -57
- package/.env.example +0 -26
- package/.env.production +0 -61
- package/.eslintrc.json +0 -0
- package/.eslintrc.override.json +0 -8
- package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -94
- package/.github/ISSUE_TEMPLATE/config.yml +0 -8
- package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -56
- package/.github/copilot-instructions.md +0 -478
- package/.github/dependabot.yml +0 -19
- package/.github/labeler.yml +0 -24
- package/.github/labels.yml +0 -70
- package/.github/pull_request_template.md +0 -42
- package/.github/release-drafter-config.yml +0 -51
- package/.github/workflows/auto-merge.yml +0 -38
- package/.github/workflows/ci.yml +0 -38
- package/.github/workflows/dependency-review.yml +0 -17
- package/.github/workflows/gemini-issue-triage.yml +0 -172
- package/.github/workflows/greetings.yml +0 -27
- package/.github/workflows/labeler.yml +0 -17
- package/.github/workflows/links.yml +0 -80
- package/.github/workflows/pr-size-labeler.yml +0 -137
- package/.github/workflows/publish-mcp.yml +0 -79
- package/.github/workflows/release-drafter.yml +0 -24
- package/.github/workflows/release.yml +0 -112
- package/.github/workflows/semantic-pull-request.yml +0 -35
- package/.github/workflows/smoke-test.yml +0 -36
- package/.github/workflows/stale.yml +0 -28
- package/CONTRIBUTING.md +0 -140
- package/Dockerfile +0 -37
- package/GEMINI.md +0 -115
- package/Public/Plugin_setup_guide.mp4 +0 -0
- package/Public/icon.png +0 -0
- package/claude_desktop_config_example.json +0 -15
- package/dist/types/responses.d.ts +0 -249
- package/dist/types/responses.js +0 -2
- package/docs/GraphQL-API.md +0 -888
- package/docs/Migration-Guide-v0.5.0.md +0 -684
- package/docs/Roadmap.md +0 -53
- package/docs/WebAssembly-Integration.md +0 -628
- package/docs/editor-plugin-extension.md +0 -370
- package/docs/handler-mapping.md +0 -249
- package/docs/native-automation-progress.md +0 -128
- package/docs/testing-guide.md +0 -423
- package/eslint.config.mjs +0 -68
- package/mcp-config-example.json +0 -14
- package/plugins/McpAutomationBridge/Config/FilterPlugin.ini +0 -8
- package/plugins/McpAutomationBridge/McpAutomationBridge.uplugin +0 -64
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/McpAutomationBridge.Build.cs +0 -189
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.cpp +0 -22
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.h +0 -30
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeHelpers.h +0 -1983
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeModule.cpp +0 -72
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSettings.cpp +0 -46
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSubsystem.cpp +0 -846
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AnimationHandlers.cpp +0 -2393
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetQueryHandlers.cpp +0 -300
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetWorkflowHandlers.cpp +0 -2807
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AudioHandlers.cpp +0 -1087
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BehaviorTreeHandlers.cpp +0 -488
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.cpp +0 -643
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.h +0 -31
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintGraphHandlers.cpp +0 -1094
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers.cpp +0 -5750
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers_List.cpp +0 -152
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ControlHandlers.cpp +0 -2614
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_DebugHandlers.cpp +0 -42
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EditorFunctionHandlers.cpp +0 -1237
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EffectHandlers.cpp +0 -1725
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EnvironmentHandlers.cpp +0 -2265
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_FoliageHandlers.cpp +0 -954
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InputHandlers.cpp +0 -209
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InsightsHandlers.cpp +0 -41
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LandscapeHandlers.cpp +0 -1164
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LevelHandlers.cpp +0 -762
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LightingHandlers.cpp +0 -663
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LogHandlers.cpp +0 -136
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_MaterialGraphHandlers.cpp +0 -494
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraGraphHandlers.cpp +0 -278
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraHandlers.cpp +0 -625
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PerformanceHandlers.cpp +0 -401
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PipelineHandlers.cpp +0 -67
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ProcessRequest.cpp +0 -472
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PropertyHandlers.cpp +0 -2634
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_RenderHandlers.cpp +0 -189
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.cpp +0 -917
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.h +0 -39
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequenceHandlers.cpp +0 -2706
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequencerHandlers.cpp +0 -519
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_TestHandlers.cpp +0 -38
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_UiHandlers.cpp +0 -668
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_WorldPartitionHandlers.cpp +0 -346
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.cpp +0 -1345
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.h +0 -149
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpConnectionManager.cpp +0 -782
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSettings.h +0 -115
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSubsystem.h +0 -796
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpConnectionManager.h +0 -117
- package/scripts/check-unreal-connection.mjs +0 -19
- package/scripts/clean-tmp.js +0 -23
- package/scripts/patch-wasm.js +0 -26
- package/scripts/run-all-tests.mjs +0 -136
- package/scripts/smoke-test.ts +0 -94
- package/scripts/sync-mcp-plugin.js +0 -143
- package/scripts/test-no-plugin-alternates.mjs +0 -113
- package/scripts/validate-server.js +0 -46
- package/scripts/verify-automation-bridge.js +0 -200
- package/src/automation/bridge.ts +0 -630
- package/src/automation/connection-manager.ts +0 -148
- package/src/automation/handshake.ts +0 -99
- package/src/automation/index.ts +0 -2
- package/src/automation/message-handler.ts +0 -192
- package/src/automation/request-tracker.ts +0 -155
- package/src/automation/types.ts +0 -108
- package/src/cli.ts +0 -34
- package/src/config/class-aliases.ts +0 -65
- package/src/config.ts +0 -73
- package/src/constants.ts +0 -29
- package/src/graphql/loaders.ts +0 -244
- package/src/graphql/resolvers.ts +0 -1008
- package/src/graphql/schema.ts +0 -452
- package/src/graphql/server.ts +0 -156
- package/src/graphql/types.ts +0 -10
- package/src/handlers/resource-handlers.ts +0 -186
- package/src/index.ts +0 -243
- package/src/resources/actors.ts +0 -127
- package/src/resources/assets.ts +0 -286
- package/src/resources/levels.ts +0 -68
- package/src/server/resource-registry.ts +0 -47
- package/src/server/tool-registry.ts +0 -354
- package/src/server-setup.ts +0 -114
- package/src/services/health-monitor.ts +0 -132
- package/src/services/metrics-server.ts +0 -176
- package/src/tools/actors.ts +0 -564
- package/src/tools/animation.ts +0 -941
- package/src/tools/assets.ts +0 -394
- package/src/tools/audio.ts +0 -499
- package/src/tools/base-tool.ts +0 -52
- package/src/tools/behavior-tree.ts +0 -45
- package/src/tools/blueprint.ts +0 -940
- package/src/tools/consolidated-tool-definitions.ts +0 -1256
- package/src/tools/consolidated-tool-handlers.ts +0 -302
- package/src/tools/debug.ts +0 -622
- package/src/tools/dynamic-handler-registry.ts +0 -33
- package/src/tools/editor.ts +0 -435
- package/src/tools/engine.ts +0 -43
- package/src/tools/environment.ts +0 -281
- package/src/tools/foliage.ts +0 -596
- package/src/tools/handlers/actor-handlers.ts +0 -244
- package/src/tools/handlers/animation-handlers.ts +0 -237
- package/src/tools/handlers/argument-helper.ts +0 -142
- package/src/tools/handlers/asset-handlers.ts +0 -550
- package/src/tools/handlers/audio-handlers.ts +0 -194
- package/src/tools/handlers/blueprint-handlers.ts +0 -380
- package/src/tools/handlers/common-handlers.ts +0 -108
- package/src/tools/handlers/editor-handlers.ts +0 -124
- package/src/tools/handlers/effect-handlers.ts +0 -224
- package/src/tools/handlers/environment-handlers.ts +0 -183
- package/src/tools/handlers/graph-handlers.ts +0 -117
- package/src/tools/handlers/input-handlers.ts +0 -28
- package/src/tools/handlers/inspect-handlers.ts +0 -450
- package/src/tools/handlers/level-handlers.ts +0 -253
- package/src/tools/handlers/lighting-handlers.ts +0 -151
- package/src/tools/handlers/performance-handlers.ts +0 -132
- package/src/tools/handlers/pipeline-handlers.ts +0 -194
- package/src/tools/handlers/sequence-handlers.ts +0 -438
- package/src/tools/handlers/system-handlers.ts +0 -564
- package/src/tools/input.ts +0 -160
- package/src/tools/introspection.ts +0 -689
- package/src/tools/landscape.ts +0 -649
- package/src/tools/level.ts +0 -989
- package/src/tools/lighting.ts +0 -1052
- package/src/tools/logs.ts +0 -219
- package/src/tools/materials.ts +0 -295
- package/src/tools/niagara.ts +0 -485
- package/src/tools/performance.ts +0 -661
- package/src/tools/physics.ts +0 -679
- package/src/tools/property-dictionary.ts +0 -98
- package/src/tools/sequence.ts +0 -385
- package/src/tools/tool-definition-utils.ts +0 -35
- package/src/tools/ui.ts +0 -452
- package/src/types/automation-responses.ts +0 -119
- package/src/types/env.ts +0 -17
- package/src/types/handler-types.ts +0 -442
- package/src/types/responses.ts +0 -355
- package/src/types/tool-interfaces.ts +0 -250
- package/src/types/tool-types.ts +0 -575
- package/src/unreal-bridge.ts +0 -693
- package/src/utils/command-validator.ts +0 -139
- package/src/utils/elicitation.ts +0 -132
- package/src/utils/error-handler.ts +0 -287
- package/src/utils/ini-reader.ts +0 -86
- package/src/utils/logger.ts +0 -35
- package/src/utils/normalize.test.ts +0 -162
- package/src/utils/normalize.ts +0 -146
- package/src/utils/path-security.ts +0 -43
- package/src/utils/response-factory.ts +0 -44
- package/src/utils/response-validator.ts +0 -395
- package/src/utils/result-helpers.ts +0 -195
- package/src/utils/safe-json.test.ts +0 -90
- package/src/utils/safe-json.ts +0 -70
- package/src/utils/unreal-command-queue.ts +0 -166
- package/src/utils/validation.test.ts +0 -184
- package/src/utils/validation.ts +0 -312
- package/src/wasm/index.ts +0 -838
- package/test-server.mjs +0 -100
- package/tests/test-animation.mjs +0 -369
- package/tests/test-asset-advanced.mjs +0 -82
- package/tests/test-asset-graph.mjs +0 -311
- package/tests/test-audio.mjs +0 -417
- package/tests/test-automation-timeouts.mjs +0 -98
- package/tests/test-behavior-tree.mjs +0 -444
- package/tests/test-blueprint-graph.mjs +0 -410
- package/tests/test-blueprint.mjs +0 -577
- package/tests/test-client-mode.mjs +0 -86
- package/tests/test-console-command.mjs +0 -56
- package/tests/test-control-actor.mjs +0 -425
- package/tests/test-control-editor.mjs +0 -112
- package/tests/test-graphql.mjs +0 -372
- package/tests/test-input.mjs +0 -349
- package/tests/test-inspect.mjs +0 -302
- package/tests/test-landscape.mjs +0 -316
- package/tests/test-lighting.mjs +0 -428
- package/tests/test-manage-asset.mjs +0 -438
- package/tests/test-manage-level.mjs +0 -89
- package/tests/test-materials.mjs +0 -356
- package/tests/test-niagara.mjs +0 -185
- package/tests/test-no-inline-python.mjs +0 -122
- package/tests/test-performance.mjs +0 -539
- package/tests/test-plugin-handshake.mjs +0 -82
- package/tests/test-runner.mjs +0 -993
- package/tests/test-sequence.mjs +0 -104
- package/tests/test-system.mjs +0 -96
- package/tests/test-wasm.mjs +0 -283
- package/tests/test-world-partition.mjs +0 -215
- package/tsconfig.json +0 -56
- package/vitest.config.ts +0 -35
- package/wasm/Cargo.lock +0 -363
- package/wasm/Cargo.toml +0 -42
- package/wasm/LICENSE +0 -21
- package/wasm/README.md +0 -253
- package/wasm/src/dependency_resolver.rs +0 -377
- package/wasm/src/lib.rs +0 -153
- package/wasm/src/property_parser.rs +0 -271
- package/wasm/src/transform_math.rs +0 -396
- package/wasm/tests/integration.rs +0 -109
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import { WebSocket } from 'ws';
|
|
2
|
-
import { Logger } from '../utils/logger.js';
|
|
3
|
-
import { randomUUID } from 'node:crypto';
|
|
4
|
-
import { SocketInfo } from './types.js';
|
|
5
|
-
import { EventEmitter } from 'node:events';
|
|
6
|
-
|
|
7
|
-
export class ConnectionManager extends EventEmitter {
|
|
8
|
-
private activeSockets = new Map<WebSocket, SocketInfo>();
|
|
9
|
-
private primarySocket?: WebSocket;
|
|
10
|
-
private heartbeatTimer?: NodeJS.Timeout;
|
|
11
|
-
private lastMessageAt?: Date;
|
|
12
|
-
private log = new Logger('ConnectionManager');
|
|
13
|
-
|
|
14
|
-
constructor(
|
|
15
|
-
private heartbeatIntervalMs: number
|
|
16
|
-
) {
|
|
17
|
-
super();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Get the configured heartbeat interval in milliseconds.
|
|
22
|
-
* @returns The heartbeat interval or 0 if disabled
|
|
23
|
-
*/
|
|
24
|
-
public getHeartbeatIntervalMs(): number {
|
|
25
|
-
return this.heartbeatIntervalMs;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
public registerSocket(
|
|
29
|
-
socket: WebSocket,
|
|
30
|
-
port: number,
|
|
31
|
-
metadata?: Record<string, unknown>,
|
|
32
|
-
remoteAddress?: string,
|
|
33
|
-
remotePort?: number
|
|
34
|
-
): void {
|
|
35
|
-
const connectionId = randomUUID();
|
|
36
|
-
const sessionId = metadata && typeof metadata.sessionId === 'string' ? (metadata.sessionId as string) : undefined;
|
|
37
|
-
const socketInfo: SocketInfo = {
|
|
38
|
-
connectionId,
|
|
39
|
-
port,
|
|
40
|
-
connectedAt: new Date(),
|
|
41
|
-
protocol: socket.protocol || undefined,
|
|
42
|
-
sessionId,
|
|
43
|
-
remoteAddress: remoteAddress ?? undefined,
|
|
44
|
-
remotePort: typeof remotePort === 'number' ? remotePort : undefined
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
this.activeSockets.set(socket, socketInfo);
|
|
48
|
-
|
|
49
|
-
// Set as primary socket if this is the first connection
|
|
50
|
-
if (!this.primarySocket) {
|
|
51
|
-
this.primarySocket = socket;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Handle WebSocket pong frames for heartbeat tracking
|
|
55
|
-
socket.on('pong', () => {
|
|
56
|
-
this.lastMessageAt = new Date();
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// Auto-cleanup on close or error
|
|
60
|
-
socket.once('close', () => {
|
|
61
|
-
this.removeSocket(socket);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
socket.once('error', (error) => {
|
|
65
|
-
this.log.error('Socket error in ConnectionManager', error);
|
|
66
|
-
this.removeSocket(socket);
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
public removeSocket(socket: WebSocket): SocketInfo | undefined {
|
|
71
|
-
const info = this.activeSockets.get(socket);
|
|
72
|
-
if (info) {
|
|
73
|
-
this.activeSockets.delete(socket);
|
|
74
|
-
if (socket === this.primarySocket) {
|
|
75
|
-
this.primarySocket = this.activeSockets.size > 0 ? this.activeSockets.keys().next().value : undefined;
|
|
76
|
-
if (this.activeSockets.size === 0) {
|
|
77
|
-
this.stopHeartbeat();
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
return info;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
public getActiveSockets(): Map<WebSocket, SocketInfo> {
|
|
85
|
-
return this.activeSockets;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
public getPrimarySocket(): WebSocket | undefined {
|
|
89
|
-
return this.primarySocket;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
public isConnected(): boolean {
|
|
93
|
-
return this.activeSockets.size > 0;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
public startHeartbeat(): void {
|
|
97
|
-
if (this.heartbeatIntervalMs <= 0) return;
|
|
98
|
-
if (this.heartbeatTimer) clearInterval(this.heartbeatTimer);
|
|
99
|
-
|
|
100
|
-
this.heartbeatTimer = setInterval(() => {
|
|
101
|
-
if (this.activeSockets.size === 0) {
|
|
102
|
-
this.stopHeartbeat();
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const pingPayload = JSON.stringify({
|
|
107
|
-
type: 'bridge_ping',
|
|
108
|
-
timestamp: new Date().toISOString()
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
for (const [socket] of this.activeSockets) {
|
|
112
|
-
if (socket.readyState === WebSocket.OPEN) {
|
|
113
|
-
try {
|
|
114
|
-
socket.ping();
|
|
115
|
-
socket.send(pingPayload);
|
|
116
|
-
} catch (error) {
|
|
117
|
-
this.log.error('Failed to send heartbeat', error);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}, this.heartbeatIntervalMs);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
public stopHeartbeat(): void {
|
|
125
|
-
if (this.heartbeatTimer) {
|
|
126
|
-
clearInterval(this.heartbeatTimer);
|
|
127
|
-
this.heartbeatTimer = undefined;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
public updateLastMessageTime(): void {
|
|
132
|
-
this.lastMessageAt = new Date();
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
public getLastMessageTime(): Date | undefined {
|
|
136
|
-
return this.lastMessageAt;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
public closeAll(code?: number, reason?: string): void {
|
|
140
|
-
this.stopHeartbeat();
|
|
141
|
-
for (const [socket] of this.activeSockets) {
|
|
142
|
-
socket.removeAllListeners();
|
|
143
|
-
socket.close(code, reason);
|
|
144
|
-
}
|
|
145
|
-
this.activeSockets.clear();
|
|
146
|
-
this.primarySocket = undefined;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import { WebSocket } from 'ws';
|
|
2
|
-
import { Logger } from '../utils/logger.js';
|
|
3
|
-
import { AutomationBridgeMessage } from './types.js';
|
|
4
|
-
import { EventEmitter } from 'node:events';
|
|
5
|
-
|
|
6
|
-
export class HandshakeHandler extends EventEmitter {
|
|
7
|
-
private log = new Logger('HandshakeHandler');
|
|
8
|
-
private readonly DEFAULT_HANDSHAKE_TIMEOUT_MS = 5000;
|
|
9
|
-
|
|
10
|
-
constructor(
|
|
11
|
-
private capabilityToken?: string
|
|
12
|
-
) {
|
|
13
|
-
super();
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
public initiateHandshake(socket: WebSocket, timeoutMs: number = this.DEFAULT_HANDSHAKE_TIMEOUT_MS): Promise<Record<string, unknown>> {
|
|
17
|
-
return new Promise((resolve, reject) => {
|
|
18
|
-
let handshakeComplete = false;
|
|
19
|
-
|
|
20
|
-
const timeout = setTimeout(() => {
|
|
21
|
-
if (!handshakeComplete) {
|
|
22
|
-
this.log.warn('Automation bridge client handshake timed out');
|
|
23
|
-
socket.close(4002, 'Handshake timeout');
|
|
24
|
-
reject(new Error('Handshake timeout'));
|
|
25
|
-
}
|
|
26
|
-
}, timeoutMs);
|
|
27
|
-
|
|
28
|
-
const onMessage = (data: any) => {
|
|
29
|
-
let parsed: AutomationBridgeMessage;
|
|
30
|
-
const text = typeof data === 'string' ? data : data.toString('utf8');
|
|
31
|
-
try {
|
|
32
|
-
parsed = JSON.parse(text) as AutomationBridgeMessage;
|
|
33
|
-
} catch (error) {
|
|
34
|
-
this.log.error('Received non-JSON automation message during handshake', error);
|
|
35
|
-
socket.close(4003, 'Invalid JSON payload');
|
|
36
|
-
cleanup();
|
|
37
|
-
reject(new Error('Invalid JSON payload'));
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (parsed.type === 'bridge_ack') {
|
|
42
|
-
handshakeComplete = true;
|
|
43
|
-
cleanup();
|
|
44
|
-
const metadata = this.sanitizeHandshakeMetadata(parsed as Record<string, unknown>);
|
|
45
|
-
resolve(metadata);
|
|
46
|
-
} else {
|
|
47
|
-
this.log.warn(`Expected bridge_ack handshake, received ${parsed.type}`);
|
|
48
|
-
socket.close(4004, 'Handshake expected bridge_ack');
|
|
49
|
-
cleanup();
|
|
50
|
-
reject(new Error(`Handshake expected bridge_ack, got ${parsed.type}`));
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const onError = (error: Error) => {
|
|
55
|
-
cleanup();
|
|
56
|
-
reject(error);
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const onClose = () => {
|
|
60
|
-
cleanup();
|
|
61
|
-
reject(new Error('Socket closed during handshake'));
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
const cleanup = () => {
|
|
65
|
-
clearTimeout(timeout);
|
|
66
|
-
socket.off('message', onMessage);
|
|
67
|
-
socket.off('error', onError);
|
|
68
|
-
socket.off('close', onClose);
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
socket.on('message', onMessage);
|
|
72
|
-
socket.on('error', onError);
|
|
73
|
-
socket.on('close', onClose);
|
|
74
|
-
|
|
75
|
-
// Send bridge_hello with a slight delay to ensure the server has registered its handlers
|
|
76
|
-
setTimeout(() => {
|
|
77
|
-
if (socket.readyState === WebSocket.OPEN) {
|
|
78
|
-
const helloPayload: AutomationBridgeMessage = {
|
|
79
|
-
type: 'bridge_hello',
|
|
80
|
-
capabilityToken: this.capabilityToken || undefined
|
|
81
|
-
};
|
|
82
|
-
this.log.debug(`Sending bridge_hello (delayed): ${JSON.stringify(helloPayload)}`);
|
|
83
|
-
socket.send(JSON.stringify(helloPayload));
|
|
84
|
-
} else {
|
|
85
|
-
this.log.warn('Socket closed before bridge_hello could be sent');
|
|
86
|
-
}
|
|
87
|
-
}, 500);
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
private sanitizeHandshakeMetadata(payload: Record<string, unknown>): Record<string, unknown> {
|
|
92
|
-
const sanitized: Record<string, unknown> = { ...payload };
|
|
93
|
-
delete sanitized.type;
|
|
94
|
-
if ('capabilityToken' in sanitized) {
|
|
95
|
-
sanitized.capabilityToken = 'REDACTED';
|
|
96
|
-
}
|
|
97
|
-
return sanitized;
|
|
98
|
-
}
|
|
99
|
-
}
|
package/src/automation/index.ts
DELETED
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
import { Logger } from '../utils/logger.js';
|
|
2
|
-
import { AutomationBridgeMessage, AutomationBridgeResponseMessage } from './types.js';
|
|
3
|
-
import { RequestTracker } from './request-tracker.js';
|
|
4
|
-
|
|
5
|
-
function FStringSafe(val: unknown): string {
|
|
6
|
-
try {
|
|
7
|
-
if (val === undefined || val === null) return '';
|
|
8
|
-
if (typeof val === 'string') return val;
|
|
9
|
-
return JSON.stringify(val);
|
|
10
|
-
} catch {
|
|
11
|
-
try { return String(val); } catch { return ''; }
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/** Response result with optional saved flag */
|
|
16
|
-
interface ResponseResult {
|
|
17
|
-
saved?: boolean;
|
|
18
|
-
action?: string;
|
|
19
|
-
success?: boolean;
|
|
20
|
-
message?: string;
|
|
21
|
-
error?: string;
|
|
22
|
-
[key: string]: unknown;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/** Event message structure */
|
|
26
|
-
interface EventMessage extends AutomationBridgeMessage {
|
|
27
|
-
requestId?: string;
|
|
28
|
-
event?: string;
|
|
29
|
-
payload?: unknown;
|
|
30
|
-
result?: ResponseResult;
|
|
31
|
-
message?: string;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/** Response with optional action field */
|
|
35
|
-
interface ResponseWithAction extends AutomationBridgeResponseMessage {
|
|
36
|
-
action?: string;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export class MessageHandler {
|
|
40
|
-
private log = new Logger('MessageHandler');
|
|
41
|
-
|
|
42
|
-
constructor(
|
|
43
|
-
private requestTracker: RequestTracker
|
|
44
|
-
) { }
|
|
45
|
-
|
|
46
|
-
public handleMessage(message: AutomationBridgeMessage): void {
|
|
47
|
-
switch (message.type) {
|
|
48
|
-
case 'automation_response':
|
|
49
|
-
this.handleAutomationResponse(message as AutomationBridgeResponseMessage);
|
|
50
|
-
break;
|
|
51
|
-
case 'bridge_ping':
|
|
52
|
-
// Handled by connection manager or ignored if client
|
|
53
|
-
break;
|
|
54
|
-
case 'bridge_pong':
|
|
55
|
-
// Handled by connection manager
|
|
56
|
-
break;
|
|
57
|
-
case 'bridge_goodbye':
|
|
58
|
-
this.log.info('Automation bridge client initiated shutdown.', message);
|
|
59
|
-
break;
|
|
60
|
-
case 'automation_event':
|
|
61
|
-
this.handleAutomationEvent(message);
|
|
62
|
-
break;
|
|
63
|
-
default:
|
|
64
|
-
this.log.debug('Received automation bridge message with no handler', message);
|
|
65
|
-
break;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
private handleAutomationResponse(response: AutomationBridgeResponseMessage): void {
|
|
70
|
-
const requestId = response.requestId;
|
|
71
|
-
if (!requestId) {
|
|
72
|
-
this.log.warn('Received automation_response without requestId');
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const pending = this.requestTracker.getPendingRequest(requestId);
|
|
77
|
-
if (!pending) {
|
|
78
|
-
this.log.debug(`No pending automation request found for requestId=${requestId}`);
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Enforce action match logic
|
|
83
|
-
const enforcedResponse = this.enforceActionMatch(response, pending.action);
|
|
84
|
-
|
|
85
|
-
if (pending.waitForEvent) {
|
|
86
|
-
if (!pending.initialResponse) {
|
|
87
|
-
// Store initial response and wait for event
|
|
88
|
-
pending.initialResponse = enforcedResponse;
|
|
89
|
-
|
|
90
|
-
// If the initial response indicates failure, resolve immediately
|
|
91
|
-
if (enforcedResponse.success === false) {
|
|
92
|
-
this.requestTracker.resolveRequest(requestId, enforcedResponse);
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// If the response indicates it's already saved/done, resolve immediately
|
|
97
|
-
const result = enforcedResponse.result as ResponseResult | undefined;
|
|
98
|
-
if (result && result.saved === true) {
|
|
99
|
-
this.requestTracker.resolveRequest(requestId, enforcedResponse);
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Set event timeout
|
|
104
|
-
const eventTimeoutMs = pending.eventTimeoutMs || 30000; // Default 30s for event
|
|
105
|
-
pending.eventTimeout = setTimeout(() => {
|
|
106
|
-
this.requestTracker.rejectRequest(requestId, new Error(`Timed out waiting for completion event for ${pending.action}`));
|
|
107
|
-
}, eventTimeoutMs);
|
|
108
|
-
|
|
109
|
-
this.log.debug(`Received initial response for ${pending.action}, waiting for completion event...`);
|
|
110
|
-
} else {
|
|
111
|
-
// Second response, treat as completion
|
|
112
|
-
this.requestTracker.resolveRequest(requestId, enforcedResponse);
|
|
113
|
-
}
|
|
114
|
-
} else {
|
|
115
|
-
this.requestTracker.resolveRequest(requestId, enforcedResponse);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
private handleAutomationEvent(message: AutomationBridgeMessage): void {
|
|
120
|
-
const evt = message as EventMessage;
|
|
121
|
-
const reqId = typeof evt.requestId === 'string' ? evt.requestId : undefined;
|
|
122
|
-
|
|
123
|
-
if (reqId) {
|
|
124
|
-
const pending = this.requestTracker.getPendingRequest(reqId);
|
|
125
|
-
if (pending) {
|
|
126
|
-
try {
|
|
127
|
-
const baseSuccess = (pending.initialResponse && typeof pending.initialResponse.success === 'boolean') ? pending.initialResponse.success : undefined;
|
|
128
|
-
const evtSuccess = (evt.result && typeof evt.result.success === 'boolean') ? !!evt.result.success : undefined;
|
|
129
|
-
|
|
130
|
-
const synthetic: AutomationBridgeResponseMessage = {
|
|
131
|
-
type: 'automation_response',
|
|
132
|
-
requestId: reqId,
|
|
133
|
-
success: evtSuccess !== undefined ? evtSuccess : baseSuccess,
|
|
134
|
-
message: typeof evt.result?.message === 'string' ? evt.result.message : (typeof evt.message === 'string' ? evt.message : FStringSafe(evt.event)),
|
|
135
|
-
error: typeof evt.result?.error === 'string' ? evt.result.error : undefined,
|
|
136
|
-
result: evt.result ?? evt.payload ?? undefined
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
this.log.info(`automation_event resolved pending request ${reqId} (event=${String(evt.event || '')})`);
|
|
140
|
-
this.requestTracker.resolveRequest(reqId, synthetic);
|
|
141
|
-
} catch (e) {
|
|
142
|
-
this.log.warn(`Failed to resolve pending automation request from automation_event ${reqId}: ${String(e)}`);
|
|
143
|
-
}
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
this.log.debug('Received automation_event (no pending request):', message);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
private enforceActionMatch(response: AutomationBridgeResponseMessage, expectedAction: string): AutomationBridgeResponseMessage {
|
|
152
|
-
try {
|
|
153
|
-
const expected = (expectedAction || '').toString().toLowerCase();
|
|
154
|
-
const echoed: string | undefined = (() => {
|
|
155
|
-
const r = response as ResponseWithAction;
|
|
156
|
-
const resultObj = response.result as ResponseResult | undefined;
|
|
157
|
-
const candidate = (typeof r.action === 'string' && r.action) || (typeof resultObj?.action === 'string' && resultObj.action);
|
|
158
|
-
return candidate || undefined;
|
|
159
|
-
})();
|
|
160
|
-
|
|
161
|
-
if (expected && echoed && typeof echoed === 'string') {
|
|
162
|
-
const got = echoed.toLowerCase();
|
|
163
|
-
|
|
164
|
-
const consolidatedToolActions = new Set([
|
|
165
|
-
'animation_physics',
|
|
166
|
-
'create_effect',
|
|
167
|
-
'build_environment',
|
|
168
|
-
'system_control',
|
|
169
|
-
'manage_ui'
|
|
170
|
-
]);
|
|
171
|
-
|
|
172
|
-
if (consolidatedToolActions.has(expected) && got !== expected) {
|
|
173
|
-
return response;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const startsEitherWay = got.startsWith(expected) || expected.startsWith(got);
|
|
177
|
-
|
|
178
|
-
if (!startsEitherWay) {
|
|
179
|
-
const mutated: ResponseWithAction = { ...response };
|
|
180
|
-
mutated.success = false;
|
|
181
|
-
if (!mutated.error) mutated.error = 'ACTION_PREFIX_MISMATCH';
|
|
182
|
-
const msgBase = typeof mutated.message === 'string' ? mutated.message + ' ' : '';
|
|
183
|
-
mutated.message = `${msgBase}Response action mismatch (expected~='${expected}', got='${echoed}')`;
|
|
184
|
-
return mutated as AutomationBridgeResponseMessage;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
} catch (e) {
|
|
188
|
-
this.log.debug('enforceActionMatch check skipped', e instanceof Error ? e.message : String(e));
|
|
189
|
-
}
|
|
190
|
-
return response;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import { PendingRequest, AutomationBridgeResponseMessage } from './types.js';
|
|
2
|
-
import { randomUUID, createHash } from 'node:crypto';
|
|
3
|
-
|
|
4
|
-
// Note: The two-phase event pattern was disabled because C++ handlers send a single response,
|
|
5
|
-
// not request+event. All actions now use simple request-response. The PendingRequest interface
|
|
6
|
-
// retains waitForEvent/eventTimeout fields for potential future use.
|
|
7
|
-
|
|
8
|
-
export class RequestTracker {
|
|
9
|
-
private pendingRequests = new Map<string, PendingRequest>();
|
|
10
|
-
private coalescedRequests = new Map<string, Promise<AutomationBridgeResponseMessage>>();
|
|
11
|
-
private lastRequestSentAt?: Date;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
constructor(
|
|
15
|
-
private maxPendingRequests: number
|
|
16
|
-
) { }
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Get the maximum number of pending requests allowed.
|
|
20
|
-
* @returns The configured maximum pending requests limit
|
|
21
|
-
*/
|
|
22
|
-
public getMaxPendingRequests(): number {
|
|
23
|
-
return this.maxPendingRequests;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Get the timestamp of when the last request was sent.
|
|
28
|
-
* @returns The Date of last request or undefined if no requests sent yet
|
|
29
|
-
*/
|
|
30
|
-
public getLastRequestSentAt(): Date | undefined {
|
|
31
|
-
return this.lastRequestSentAt;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Update the last request sent timestamp.
|
|
36
|
-
* Called when a new request is dispatched.
|
|
37
|
-
*/
|
|
38
|
-
public updateLastRequestSentAt(): void {
|
|
39
|
-
this.lastRequestSentAt = new Date();
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Create a new pending request with timeout handling.
|
|
44
|
-
* @param action - The action name being requested
|
|
45
|
-
* @param payload - The request payload
|
|
46
|
-
* @param timeoutMs - Timeout in milliseconds before the request fails
|
|
47
|
-
* @returns Object containing the requestId and a promise that resolves with the response
|
|
48
|
-
* @throws Error if max pending requests limit is reached
|
|
49
|
-
*/
|
|
50
|
-
public createRequest(
|
|
51
|
-
action: string,
|
|
52
|
-
payload: Record<string, unknown>,
|
|
53
|
-
timeoutMs: number
|
|
54
|
-
): { requestId: string; promise: Promise<AutomationBridgeResponseMessage> } {
|
|
55
|
-
if (this.pendingRequests.size >= this.maxPendingRequests) {
|
|
56
|
-
throw new Error(`Max pending requests limit reached (${this.maxPendingRequests})`);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const requestId = randomUUID();
|
|
60
|
-
|
|
61
|
-
const promise = new Promise<AutomationBridgeResponseMessage>((resolve, reject) => {
|
|
62
|
-
const timeout = setTimeout(() => {
|
|
63
|
-
if (this.pendingRequests.has(requestId)) {
|
|
64
|
-
this.pendingRequests.delete(requestId);
|
|
65
|
-
reject(new Error(`Request ${requestId} timed out after ${timeoutMs}ms`));
|
|
66
|
-
}
|
|
67
|
-
}, timeoutMs);
|
|
68
|
-
|
|
69
|
-
this.pendingRequests.set(requestId, {
|
|
70
|
-
resolve,
|
|
71
|
-
reject,
|
|
72
|
-
timeout,
|
|
73
|
-
action,
|
|
74
|
-
payload,
|
|
75
|
-
requestedAt: new Date(),
|
|
76
|
-
// Note: waitForEvent and eventTimeoutMs are preserved for potential future use
|
|
77
|
-
// but currently all actions use simple request-response pattern
|
|
78
|
-
waitForEvent: false,
|
|
79
|
-
eventTimeoutMs: timeoutMs
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
return { requestId, promise };
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
public getPendingRequest(requestId: string): PendingRequest | undefined {
|
|
87
|
-
return this.pendingRequests.get(requestId);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
public resolveRequest(requestId: string, response: AutomationBridgeResponseMessage): void {
|
|
91
|
-
const pending = this.pendingRequests.get(requestId);
|
|
92
|
-
if (pending) {
|
|
93
|
-
clearTimeout(pending.timeout);
|
|
94
|
-
if (pending.eventTimeout) clearTimeout(pending.eventTimeout);
|
|
95
|
-
this.pendingRequests.delete(requestId);
|
|
96
|
-
pending.resolve(response);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
public rejectRequest(requestId: string, error: Error): void {
|
|
101
|
-
const pending = this.pendingRequests.get(requestId);
|
|
102
|
-
if (pending) {
|
|
103
|
-
clearTimeout(pending.timeout);
|
|
104
|
-
if (pending.eventTimeout) clearTimeout(pending.eventTimeout);
|
|
105
|
-
this.pendingRequests.delete(requestId);
|
|
106
|
-
pending.reject(error);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
public rejectAll(error: Error): void {
|
|
111
|
-
for (const [, pending] of this.pendingRequests) {
|
|
112
|
-
clearTimeout(pending.timeout);
|
|
113
|
-
if (pending.eventTimeout) clearTimeout(pending.eventTimeout);
|
|
114
|
-
pending.reject(error);
|
|
115
|
-
}
|
|
116
|
-
this.pendingRequests.clear();
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
public getPendingCount(): number {
|
|
120
|
-
return this.pendingRequests.size;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
public getPendingDetails(): Array<{ requestId: string; action: string; ageMs: number }> {
|
|
124
|
-
const now = Date.now();
|
|
125
|
-
return Array.from(this.pendingRequests.entries()).map(([id, pending]) => ({
|
|
126
|
-
requestId: id,
|
|
127
|
-
action: pending.action,
|
|
128
|
-
ageMs: Math.max(0, now - pending.requestedAt.getTime())
|
|
129
|
-
}));
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
public getCoalescedRequest(key: string): Promise<AutomationBridgeResponseMessage> | undefined {
|
|
133
|
-
return this.coalescedRequests.get(key);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
public setCoalescedRequest(key: string, promise: Promise<AutomationBridgeResponseMessage>): void {
|
|
137
|
-
this.coalescedRequests.set(key, promise);
|
|
138
|
-
// Remove from map when settled
|
|
139
|
-
promise.finally(() => {
|
|
140
|
-
if (this.coalescedRequests.get(key) === promise) {
|
|
141
|
-
this.coalescedRequests.delete(key);
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
public createCoalesceKey(action: string, payload: Record<string, unknown>): string {
|
|
147
|
-
// Only coalesce read-only operations
|
|
148
|
-
const readOnlyActions = ['list', 'get_', 'exists', 'search', 'find'];
|
|
149
|
-
if (!readOnlyActions.some(a => action.startsWith(a))) return '';
|
|
150
|
-
|
|
151
|
-
// Create a stable hash of the payload
|
|
152
|
-
const stablePayload = JSON.stringify(payload, Object.keys(payload).sort());
|
|
153
|
-
return `${action}:${createHash('md5').update(stablePayload).digest('hex')}`;
|
|
154
|
-
}
|
|
155
|
-
}
|