ue-mcp 1.1.44 → 1.2.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/action-class.d.ts +30 -0
- package/dist/action-class.js +217 -0
- package/dist/action-class.js.map +1 -0
- package/dist/asset-path.d.ts +49 -0
- package/dist/asset-path.js +124 -0
- package/dist/asset-path.js.map +1 -0
- package/dist/auth-cli.d.ts +1 -1
- package/dist/auth-cli.js +1 -1
- package/dist/bridge.d.ts +179 -4
- package/dist/bridge.js +375 -32
- package/dist/bridge.js.map +1 -1
- package/dist/build-cli.js +12 -1
- package/dist/build-cli.js.map +1 -1
- package/dist/context-cli.js +22 -7
- package/dist/context-cli.js.map +1 -1
- package/dist/cpp-parser.js +1 -1
- package/dist/deploy-cli.js +11 -2
- package/dist/deploy-cli.js.map +1 -1
- package/dist/deployer.d.ts +1 -1
- package/dist/deployer.js +4 -4
- package/dist/doctor.d.ts +14 -6
- package/dist/doctor.js +93 -31
- package/dist/doctor.js.map +1 -1
- package/dist/editor-control.d.ts +10 -2
- package/dist/editor-control.js +222 -63
- package/dist/editor-control.js.map +1 -1
- package/dist/editor-flag.d.ts +61 -0
- package/dist/editor-flag.js +258 -0
- package/dist/editor-flag.js.map +1 -0
- package/dist/editor-gate.d.ts +65 -0
- package/dist/editor-gate.js +124 -0
- package/dist/editor-gate.js.map +1 -0
- package/dist/editor-target.d.ts +70 -0
- package/dist/editor-target.js +117 -0
- package/dist/editor-target.js.map +1 -0
- package/dist/engine-observer.d.ts +20 -4
- package/dist/engine-observer.js +35 -9
- package/dist/engine-observer.js.map +1 -1
- package/dist/epic-enrich.d.ts +9 -0
- package/dist/epic-enrich.js +107 -5
- package/dist/epic-enrich.js.map +1 -1
- package/dist/errors.d.ts +14 -1
- package/dist/errors.js +3 -1
- package/dist/errors.js.map +1 -1
- package/dist/feedback-cli.d.ts +1 -1
- package/dist/feedback-cli.js +106 -13
- package/dist/feedback-cli.js.map +1 -1
- package/dist/feedback-routing.js +2 -2
- package/dist/feedback-routing.js.map +1 -1
- package/dist/flow/bridge-task.js +5 -1
- package/dist/flow/bridge-task.js.map +1 -1
- package/dist/flow/context.d.ts +1 -1
- package/dist/flow/flow-tool.d.ts +12 -2
- package/dist/flow/flow-tool.js +18 -14
- package/dist/flow/flow-tool.js.map +1 -1
- package/dist/flow/guard.d.ts +4 -1
- package/dist/flow/guard.js +2 -2
- package/dist/flow/guard.js.map +1 -1
- package/dist/flow/guarded-bridge.d.ts +11 -2
- package/dist/flow/guarded-bridge.js +13 -2
- package/dist/flow/guarded-bridge.js.map +1 -1
- package/dist/flow/http-server.d.ts +1 -1
- package/dist/flow/http-server.js +38 -4
- package/dist/flow/http-server.js.map +1 -1
- package/dist/flow/loader.d.ts +1 -1
- package/dist/flow/loader.js +11 -11
- package/dist/flow/registry.js +1 -1
- package/dist/flow/task-factory.js +6 -3
- package/dist/flow/task-factory.js.map +1 -1
- package/dist/flow/task-guards.js +7 -1
- package/dist/flow/task-guards.js.map +1 -1
- package/dist/flow/write-methods.js +35 -0
- package/dist/flow/write-methods.js.map +1 -1
- package/dist/function-args.d.ts +42 -0
- package/dist/function-args.js +126 -0
- package/dist/function-args.js.map +1 -0
- package/dist/github-app.d.ts +12 -1
- package/dist/github-app.js +169 -75
- package/dist/github-app.js.map +1 -1
- package/dist/hook-handler.d.ts +1 -1
- package/dist/hook-handler.js +15 -48
- package/dist/hook-handler.js.map +1 -1
- package/dist/hook-installer.js +2 -2
- package/dist/hook-session.d.ts +38 -0
- package/dist/hook-session.js +127 -0
- package/dist/hook-session.js.map +1 -0
- package/dist/index.js +464 -165
- package/dist/index.js.map +1 -1
- package/dist/init.js +39 -22
- package/dist/init.js.map +1 -1
- package/dist/instructions.d.ts +9 -3
- package/dist/instructions.js +77 -26
- package/dist/instructions.js.map +1 -1
- package/dist/lean-context.d.ts +9 -0
- package/dist/lean-context.js +10 -1
- package/dist/lean-context.js.map +1 -1
- package/dist/locking.d.ts +17 -2
- package/dist/locking.js +47 -12
- package/dist/locking.js.map +1 -1
- package/dist/mcp-client-config.d.ts +1 -1
- package/dist/mcp-client-config.js +1 -1
- package/dist/plugin/injection.js +1 -1
- package/dist/plugin/loader.js +5 -5
- package/dist/plugin/native-deploy.d.ts +1 -1
- package/dist/plugin/native-deploy.js +1 -1
- package/dist/plugin-cli.js +33 -12
- package/dist/plugin-cli.js.map +1 -1
- package/dist/plugin-freshness.d.ts +11 -3
- package/dist/plugin-freshness.js +19 -4
- package/dist/plugin-freshness.js.map +1 -1
- package/dist/port.d.ts +2 -2
- package/dist/port.js +2 -2
- package/dist/privacy-scrub.d.ts +14 -1
- package/dist/privacy-scrub.js +8 -0
- package/dist/privacy-scrub.js.map +1 -1
- package/dist/project-switch.d.ts +23 -0
- package/dist/project-switch.js +73 -0
- package/dist/project-switch.js.map +1 -0
- package/dist/project.d.ts +31 -1
- package/dist/project.js +92 -28
- package/dist/project.js.map +1 -1
- package/dist/registry-catalog.d.ts +12 -0
- package/dist/registry-catalog.js +14 -0
- package/dist/registry-catalog.js.map +1 -1
- package/dist/requested-port.d.ts +63 -0
- package/dist/requested-port.js +102 -0
- package/dist/requested-port.js.map +1 -0
- package/dist/resolve.js +28 -4
- package/dist/resolve.js.map +1 -1
- package/dist/schemas.d.ts +63 -0
- package/dist/schemas.js +29 -0
- package/dist/schemas.js.map +1 -1
- package/dist/session-env.d.ts +31 -0
- package/dist/session-env.js +47 -0
- package/dist/session-env.js.map +1 -0
- package/dist/session-surface.d.ts +51 -0
- package/dist/session-surface.js +142 -0
- package/dist/session-surface.js.map +1 -0
- package/dist/session.d.ts +144 -0
- package/dist/session.js +317 -0
- package/dist/session.js.map +1 -0
- package/dist/tool-counts.json +11 -11
- package/dist/tool-search.d.ts +1 -1
- package/dist/tool-search.js +6 -3
- package/dist/tool-search.js.map +1 -1
- package/dist/tools/animation.js +43 -9
- package/dist/tools/animation.js.map +1 -1
- package/dist/tools/asset.js +227 -23
- package/dist/tools/asset.js.map +1 -1
- package/dist/tools/blueprint.js +11 -5
- package/dist/tools/blueprint.js.map +1 -1
- package/dist/tools/chooser.js +1 -1
- package/dist/tools/editor.js +120 -29
- package/dist/tools/editor.js.map +1 -1
- package/dist/tools/feedback.js +95 -32
- package/dist/tools/feedback.js.map +1 -1
- package/dist/tools/level.js +21 -6
- package/dist/tools/level.js.map +1 -1
- package/dist/tools/material.js +1 -1
- package/dist/tools/project.js +204 -17
- package/dist/tools/project.js.map +1 -1
- package/dist/tools/reflection.js +3 -3
- package/dist/tools/reflection.js.map +1 -1
- package/dist/tools/widget-params.d.ts +5 -0
- package/dist/tools/widget-params.js +117 -0
- package/dist/tools/widget-params.js.map +1 -0
- package/dist/tools/widget.js +56 -22
- package/dist/tools/widget.js.map +1 -1
- package/dist/tools.d.ts +4 -0
- package/dist/tools.js +22 -0
- package/dist/tools.js.map +1 -1
- package/dist/types.d.ts +120 -7
- package/dist/types.js +162 -7
- package/dist/types.js.map +1 -1
- package/dist/ue-mcp.default.yml +182 -62
- package/dist/ui/select.js +3 -3
- package/dist/uninstall-hooks.d.ts +1 -1
- package/dist/uninstall-hooks.js +13 -3
- package/dist/uninstall-hooks.js.map +1 -1
- package/dist/update.js +33 -13
- package/dist/update.js.map +1 -1
- package/dist/user-state.d.ts +12 -2
- package/dist/user-state.js +39 -6
- package/dist/user-state.js.map +1 -1
- package/dist/version-check.d.ts +14 -0
- package/dist/version-check.js +60 -1
- package/dist/version-check.js.map +1 -1
- package/dist/workaround-tracker.d.ts +29 -6
- package/dist/workaround-tracker.js +39 -10
- package/dist/workaround-tracker.js.map +1 -1
- package/package.json +7 -3
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/BridgeParamEcho.cpp +124 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/BridgeParamEcho.h +68 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/BridgeServer.cpp +1682 -320
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/BridgeServer.h +255 -21
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/BridgeStateFiles.cpp +419 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/BridgeStateFiles.h +150 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/GameThreadExecutor.cpp +32 -7
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/GameThreadExecutor.h +9 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerJsonProperty.h +176 -39
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerPropertyText.h +399 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.cpp +842 -33
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.h +14 -6
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_MotionMatching.cpp +1 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_Sequence.cpp +10 -10
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_StateMachine.cpp +5 -5
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers.cpp +276 -84
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers.h +23 -6
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkProperties.cpp +542 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkUpsert.cpp +811 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Enum.cpp +1 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Import.cpp +6 -6
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Mesh.cpp +543 -8
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_RenderTarget.cpp +242 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Sockets.cpp +1 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AudioHandlers.cpp +1 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.cpp +268 -50
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.h +5 -5
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Functions.cpp +230 -5
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Graph.cpp +25 -31
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Properties.cpp +32 -5
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ChooserHandlers.cpp +1 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ChooserHandlers.h +1 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DemoHandlers.cpp +4 -4
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DialogHandlers.cpp +1 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DiffHandlers.h +2 -2
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers.cpp +347 -99
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers.h +6 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_PIE.cpp +235 -6
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_PIERuntime.cpp +610 -28
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers.cpp +4 -3
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers.h +3 -3
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_Input.cpp +8 -8
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.h +1 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers.cpp +325 -8
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers.h +11 -3
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Lights.cpp +205 -32
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_MultiLevel.cpp +739 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Trace.cpp +101 -4
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_WorldPartition.cpp +87 -16
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LockHandlers.h +1 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers.cpp +19 -4
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers.h +1 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers_Advanced.cpp +4 -4
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NiagaraHandlers.cpp +6 -6
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NiagaraHandlers.h +2 -2
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PCGHandlers.cpp +7 -7
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PCGHandlers.h +3 -3
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ProjectHandlers.cpp +8 -8
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ProjectHandlers.h +3 -3
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ReflectionHandlers.cpp +13 -29
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers.cpp +890 -66
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers.h +16 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers_Extraction.cpp +598 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers_Interaction.cpp +552 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers_Properties.cpp +3 -3
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers_RuntimeState.cpp +232 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/LockRegistry.h +2 -2
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetBulkUpsertTests.cpp +141 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/BridgeProtocolTests.cpp +818 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/WidgetExtractSubtreeTests.cpp +32 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/UE_MCP_Bridge.cpp +12 -11
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/HandlerUtils.h +416 -18
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/JsonSerializer.cpp +124 -5
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/JsonSerializer.h +1 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/MCPHandlerRegistration.h +20 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/UE_MCP_Bridge.Build.cs +9 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Private/MCPEngineStatus.cpp +34 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Public/MCPEngineStatus.h +6 -3
- package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/UE_MCP_BridgeStatus.Build.cs +2 -2
- package/skills/ue-mcp-blueprint/SKILL.md +16 -16
- package/skills/ue-mcp-native-cpp/SKILL.md +7 -7
- package/skills/ue-mcp-niagara/SKILL.md +17 -17
- package/skills/ue-mcp-workflow/SKILL.md +11 -11
- package/assets/installation.bin +0 -0
- package/dist/manifest-signature.d.ts +0 -1
- package/dist/manifest-signature.js +0 -53
- package/dist/manifest-signature.js.map +0 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://github.com/db-lyon/ue-mcp/stargazers)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
|
|
8
|
-
**Unreal Engine Model Context Protocol Server** - gives AI assistants deep read/write access to the Unreal Editor through <!-- count:tools -->24<!-- /count --> category tools covering <!-- count:actions -->
|
|
8
|
+
**Unreal Engine Model Context Protocol Server** - gives AI assistants deep read/write access to the Unreal Editor through <!-- count:tools -->24<!-- /count --> category tools covering <!-- count:actions -->783+<!-- /count --> actions, plus a YAML flow engine for multi-step workflows and an npm plugin system for extending the surface.
|
|
9
9
|
|
|
10
10
|
On UE 5.8+ it also wraps Epic's entire native AI Toolset Registry - 830 official Unreal tools, called in-process and surfaced as `epic_*` actions in the matching category: Sequencer in `animation`, PCG in `pcg`, static meshes in `asset`.
|
|
11
11
|
|
|
@@ -137,7 +137,7 @@ flows:
|
|
|
137
137
|
flow(action="run", flowName="build_and_check")
|
|
138
138
|
```
|
|
139
139
|
|
|
140
|
-
Every one of the <!-- count:actions -->
|
|
140
|
+
Every one of the <!-- count:actions -->783+<!-- /count --> actions is also a flow task. Flows support step references, retries, rollback, custom tasks in your own `.js`/`.ts`, and shell steps. See [Flows](https://ue-mcp.com/docs/flows/).
|
|
141
141
|
|
|
142
142
|
## Plugins
|
|
143
143
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type ActionClass = "read" | "mutate" | "unknown";
|
|
2
|
+
/** Where a classification came from. `unresolved` is what the drift guard fails on. */
|
|
3
|
+
export type ActionClassSource = "override" | "lexicon" | "epic-default" | "unresolved";
|
|
4
|
+
export interface ActionClassification {
|
|
5
|
+
class: ActionClass;
|
|
6
|
+
source: ActionClassSource;
|
|
7
|
+
}
|
|
8
|
+
/** Split `category.action`, tolerating an action name that contains a dot. */
|
|
9
|
+
export declare function splitTaskName(taskName: string): {
|
|
10
|
+
tool: string;
|
|
11
|
+
action: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Classify one action.
|
|
15
|
+
*
|
|
16
|
+
* Order: explicit override, then the verb lexicon over every underscore
|
|
17
|
+
* segment (a mutate verb anywhere wins, because `metasound_add_node` adds a
|
|
18
|
+
* node and `cue_get_graph` does not), then the Epic default, then unresolved.
|
|
19
|
+
*/
|
|
20
|
+
export declare function classifyActionClass(tool: string, action: string): ActionClassification;
|
|
21
|
+
/** Convenience over a `category.action` task name. */
|
|
22
|
+
export declare function classifyTaskClass(taskName: string): ActionClassification;
|
|
23
|
+
/**
|
|
24
|
+
* Does this class need the caller to name an editor?
|
|
25
|
+
*
|
|
26
|
+
* `unknown` is gated exactly like `mutate`. The whole point of keeping it as a
|
|
27
|
+
* distinct label is that it is not a guess; the gate treats a thing that might
|
|
28
|
+
* be a mutation as a mutation.
|
|
29
|
+
*/
|
|
30
|
+
export declare function requiresExplicitEditor(cls: ActionClass): boolean;
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read / mutate / unknown classification of the action surface (#817, plan 5.1).
|
|
3
|
+
*
|
|
4
|
+
* This exists for one decision: while this server drives more than one editor,
|
|
5
|
+
* a call that does not name its target falls through to the active session. For
|
|
6
|
+
* a read that is harmless. For anything that changes an editor, its project on
|
|
7
|
+
* disk, or its process, a wrong guess edits somebody else's project, so those
|
|
8
|
+
* calls have to name the editor they mean.
|
|
9
|
+
*
|
|
10
|
+
* Why this is not `flow/write-methods.ts` or `locking.ts`:
|
|
11
|
+
*
|
|
12
|
+
* - `classifyWrite` (source-control guard) answers "which content paths is
|
|
13
|
+
* this call about to write", and returns `writes: false` whenever it cannot
|
|
14
|
+
* extract a path. A call with no asset path in its params is still a
|
|
15
|
+
* mutation of the editor.
|
|
16
|
+
* - `classifyAction` (asset locking) answers "should this call take a lock",
|
|
17
|
+
* and deliberately collapses everything it does not recognise into
|
|
18
|
+
* `mutates: false` so locking never blocks a call it cannot classify.
|
|
19
|
+
*
|
|
20
|
+
* Both are load-bearing where they are and both fail open, which is the exact
|
|
21
|
+
* opposite of what a routing gate needs. So this module answers a third
|
|
22
|
+
* question, three-way, and fails closed. It is not a parallel scheme: the verb
|
|
23
|
+
* lexicon is `locking.ts`'s, imported and extended rather than restated, and a
|
|
24
|
+
* test asserts this module never contradicts locking's verdict.
|
|
25
|
+
*
|
|
26
|
+
* The taxonomy is stated in terms of the ADDRESSED EDITOR:
|
|
27
|
+
*
|
|
28
|
+
* read observes. Does not change the editor, its project on disk, or its
|
|
29
|
+
* process. Landing one in the wrong editor returns the wrong answer
|
|
30
|
+
* and changes nothing.
|
|
31
|
+
* mutate may change any of those three, or has an external side effect
|
|
32
|
+
* (writes a file, posts an issue, launches or quits a process).
|
|
33
|
+
* unknown cannot be determined from the action alone, because what it does is
|
|
34
|
+
* decided by a parameter (an arbitrary python string, a wrapped tool
|
|
35
|
+
* name). Gated exactly like `mutate`.
|
|
36
|
+
*
|
|
37
|
+
* Unclassifiable is a real answer here, not a shrug: an `unknown` action still
|
|
38
|
+
* requires an explicit target, so the honest label costs nothing at the gate
|
|
39
|
+
* and stops a guess from being recorded as fact.
|
|
40
|
+
*/
|
|
41
|
+
import { MUTATE_PREFIXES, READ_PREFIXES } from "./locking.js";
|
|
42
|
+
/**
|
|
43
|
+
* Verbs that mean "this call changes something".
|
|
44
|
+
*
|
|
45
|
+
* Seeded from the locking lexicon so the two cannot drift apart, then extended
|
|
46
|
+
* with the verbs the action surface uses that locking never had to recognise
|
|
47
|
+
* (locking only cares about asset writes; this also has to catch process
|
|
48
|
+
* lifecycle, editor UI state, and anything with an effect outside the editor).
|
|
49
|
+
*
|
|
50
|
+
* Adding a verb here can only ever ask for an explicit target where one was not
|
|
51
|
+
* required before. That is the safe direction, so this list is generous.
|
|
52
|
+
*/
|
|
53
|
+
const MUTATE_VERBS = new Set([
|
|
54
|
+
...MUTATE_PREFIXES,
|
|
55
|
+
// Arbitrary code and arbitrary engine commands.
|
|
56
|
+
"execute", "run", "invoke", "call", "eval",
|
|
57
|
+
// Process and session lifecycle.
|
|
58
|
+
"start", "stop", "restart", "quit", "kill", "launch", "request", "hot", "cook", "deploy",
|
|
59
|
+
// Editor and viewport state a user would see happen in the wrong window.
|
|
60
|
+
"open", "close", "focus", "select", "play", "simulate", "possess", "eject",
|
|
61
|
+
"pause", "resume", "teleport", "respond", "stage", "capture", "render",
|
|
62
|
+
// Authoring verbs the asset lexicon has no reason to know about.
|
|
63
|
+
"author", "edit", "place", "load", "reload", "force", "regenerate", "recompile",
|
|
64
|
+
"rebuild", "reparent", "auto", "populate", "bind", "rebind", "fill", "append",
|
|
65
|
+
"reindex", "migrate", "override", "flush", "cleanup", "configure", "init",
|
|
66
|
+
"initialize", "step", "go", "submit", "remap", "login", "logout", "sync",
|
|
67
|
+
"toggle", "reactivate", "reorder", "wrap", "sculpt", "paint", "snap", "aim",
|
|
68
|
+
"undo", "redo", "purge", "begin", "end", "lock", "unlock", "drop", "retarget",
|
|
69
|
+
"install", "uninstall", "restore", "revert", "activate", "deactivate",
|
|
70
|
+
"trigger", "emit", "send", "post", "publish", "upload", "convert", "promote",
|
|
71
|
+
"mark", "dirty", "refresh", "trim", "crop", "resize", "rotate", "translate",
|
|
72
|
+
"transform", "split", "merge", "patch", "seek", "mute", "unmute",
|
|
73
|
+
// Verbs the wrapped engine surface uses that no native action does. Every one
|
|
74
|
+
// of these names a tool that edits a graph, moves a control, drives the UI, or
|
|
75
|
+
// writes a file, and without them the Epic default below would let it through
|
|
76
|
+
// untargeted.
|
|
77
|
+
"paste", "copy", "press", "type", "click", "drag", "hover", "scroll", "break",
|
|
78
|
+
"arrange", "reposition", "layout", "commit", "zero", "tween", "key",
|
|
79
|
+
"collapse", "expand", "change", "tag", "untag", "fix", "draw", "mirror",
|
|
80
|
+
"blend", "empty", "hide", "show", "construct", "frame", "screenshot", "look",
|
|
81
|
+
]);
|
|
82
|
+
/**
|
|
83
|
+
* Verbs that mean "this call only looks".
|
|
84
|
+
*
|
|
85
|
+
* Kept deliberately short. A wrong entry here is the dangerous direction: it
|
|
86
|
+
* would let a mutation through untargeted. Anything even slightly ambiguous
|
|
87
|
+
* gets an explicit override below instead of a verb.
|
|
88
|
+
*/
|
|
89
|
+
const READ_VERBS = new Set([
|
|
90
|
+
...READ_PREFIXES,
|
|
91
|
+
"is", "scan", "sample", "health", "diagnose", "compare", "query", "dump",
|
|
92
|
+
"fetch", "lookup", "enumerate",
|
|
93
|
+
]);
|
|
94
|
+
/**
|
|
95
|
+
* Actions the verb lexicon gets wrong, or cannot see.
|
|
96
|
+
*
|
|
97
|
+
* Every entry is a decision about one action, so every entry carries the reason
|
|
98
|
+
* it is not what the verb says. Keyed `category.action`.
|
|
99
|
+
*/
|
|
100
|
+
const OVERRIDES = {
|
|
101
|
+
// ── Address the server's session registry, never an editor ──────────
|
|
102
|
+
// Routing cannot land these in the wrong editor: they do not reach a bridge
|
|
103
|
+
// and they name their subject in their own parameters. Requiring an `editor`
|
|
104
|
+
// target for "register an editor" would be a riddle, not a safeguard.
|
|
105
|
+
"project.list_editors": "read",
|
|
106
|
+
"project.use_editor": "read",
|
|
107
|
+
"project.add_editor": "read",
|
|
108
|
+
"project.drop_editor": "read",
|
|
109
|
+
// Renders a flow's execution plan without running a step of it. `flow.run`
|
|
110
|
+
// is a mutation by the lexicon, which is correct: a flow is whatever its
|
|
111
|
+
// steps are.
|
|
112
|
+
"flow.plan": "read",
|
|
113
|
+
// ── Arbitrary payload decides the effect ────────────────────────────
|
|
114
|
+
"epic.call_tool": "unknown",
|
|
115
|
+
"editor.execute_python": "mutate",
|
|
116
|
+
"project.execute_python_report": "mutate",
|
|
117
|
+
"editor.execute_command": "mutate",
|
|
118
|
+
"editor.invoke_object_function": "unknown",
|
|
119
|
+
"editor.invoke_object_functions": "unknown",
|
|
120
|
+
"editor.invoke_static_function": "unknown",
|
|
121
|
+
"editor.invoke_function": "unknown",
|
|
122
|
+
"widget.invoke_runtime_function": "unknown",
|
|
123
|
+
"niagara.batch": "mutate",
|
|
124
|
+
// ── Reads whose verb reads as a write ───────────────────────────────
|
|
125
|
+
// Serializers: they render a graph as text or JSON and return it.
|
|
126
|
+
"blueprint.export_nodes_t3d": "read",
|
|
127
|
+
"material.export_graph": "read",
|
|
128
|
+
"pcg.export_graph": "read",
|
|
129
|
+
// Reads the actor descriptors of an unloaded World Partition level. Nothing
|
|
130
|
+
// is opened; `level.load` is the action that changes the open map.
|
|
131
|
+
"level.load_actor_descs": "read",
|
|
132
|
+
// Extracts a widget subtree as a description. `widget.author` writes one.
|
|
133
|
+
"widget.extract_subtree": "read",
|
|
134
|
+
// Cache metadata about the Fab library, not a cache write.
|
|
135
|
+
"fab.cache_info": "read",
|
|
136
|
+
// Reads a mirror data table. "mirror" is a mutate verb because the wrapped
|
|
137
|
+
// engine surface uses it as one (mirror_selected_controls), and a mutate verb
|
|
138
|
+
// anywhere in the name wins, which is wrong for exactly this action.
|
|
139
|
+
"animation.read_mirror_data_table": "read",
|
|
140
|
+
// Reads whose first segment is not a verb at all.
|
|
141
|
+
"level.line_trace": "read",
|
|
142
|
+
"level.nav_project_point": "read",
|
|
143
|
+
"level.count_actors_by_class": "read",
|
|
144
|
+
"gameplay.project_to_nav": "read",
|
|
145
|
+
"gameplay.find_nav_path": "read",
|
|
146
|
+
"editor.hit_test_viewport_pixel": "read",
|
|
147
|
+
"editor.check_for_crashes": "read",
|
|
148
|
+
"editor.search_log": "read",
|
|
149
|
+
"project.live_coding_status": "read",
|
|
150
|
+
"feedback.route": "read",
|
|
151
|
+
"epic.status": "read",
|
|
152
|
+
"fab.status": "read",
|
|
153
|
+
// ── Writes whose verb reads as a read ───────────────────────────────
|
|
154
|
+
// Drives the editor's preview: it plays an animation in a viewport.
|
|
155
|
+
"animation.preview_animation": "mutate",
|
|
156
|
+
// Renders to a file on disk.
|
|
157
|
+
"material.render_preview": "mutate",
|
|
158
|
+
"asset.export": "mutate",
|
|
159
|
+
"asset.export_texture": "mutate",
|
|
160
|
+
"level.export_actor_fbx": "mutate",
|
|
161
|
+
"audio.extract_pcm": "mutate",
|
|
162
|
+
// Rebuilds the full-text index in the editor's own database.
|
|
163
|
+
"asset.reindex_fts": "mutate",
|
|
164
|
+
// Posts to a public issue tracker.
|
|
165
|
+
"feedback.submit": "mutate",
|
|
166
|
+
};
|
|
167
|
+
/** Split `category.action`, tolerating an action name that contains a dot. */
|
|
168
|
+
export function splitTaskName(taskName) {
|
|
169
|
+
const i = taskName.indexOf(".");
|
|
170
|
+
if (i < 0)
|
|
171
|
+
return { tool: taskName, action: "" };
|
|
172
|
+
return { tool: taskName.slice(0, i), action: taskName.slice(i + 1) };
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Classify one action.
|
|
176
|
+
*
|
|
177
|
+
* Order: explicit override, then the verb lexicon over every underscore
|
|
178
|
+
* segment (a mutate verb anywhere wins, because `metasound_add_node` adds a
|
|
179
|
+
* node and `cue_get_graph` does not), then the Epic default, then unresolved.
|
|
180
|
+
*/
|
|
181
|
+
export function classifyActionClass(tool, action) {
|
|
182
|
+
const key = `${tool}.${action}`;
|
|
183
|
+
const override = OVERRIDES[key];
|
|
184
|
+
if (override)
|
|
185
|
+
return { class: override, source: "override" };
|
|
186
|
+
const segments = action.toLowerCase().split(/[._]/).filter(Boolean);
|
|
187
|
+
if (segments.some((s) => MUTATE_VERBS.has(s)))
|
|
188
|
+
return { class: "mutate", source: "lexicon" };
|
|
189
|
+
if (segments.some((s) => READ_VERBS.has(s)))
|
|
190
|
+
return { class: "read", source: "lexicon" };
|
|
191
|
+
// Epic's wrapped engine tools are injected at runtime from a live catalog, so
|
|
192
|
+
// no build-time guard can enumerate them: enrichment can invent whole
|
|
193
|
+
// categories from a toolset this package has never seen. The surface is
|
|
194
|
+
// overwhelmingly read-shaped and a wrapped tool that writes almost always
|
|
195
|
+
// says so in its name, which the lexicon above already caught. Defaulting the
|
|
196
|
+
// remainder to `unknown` would make every unbaked Epic action a hard error
|
|
197
|
+
// for multi-editor users, so it defaults to `read` (plan 5.1).
|
|
198
|
+
if (action.startsWith("epic_"))
|
|
199
|
+
return { class: "read", source: "epic-default" };
|
|
200
|
+
return { class: "unknown", source: "unresolved" };
|
|
201
|
+
}
|
|
202
|
+
/** Convenience over a `category.action` task name. */
|
|
203
|
+
export function classifyTaskClass(taskName) {
|
|
204
|
+
const { tool, action } = splitTaskName(taskName);
|
|
205
|
+
return classifyActionClass(tool, action);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Does this class need the caller to name an editor?
|
|
209
|
+
*
|
|
210
|
+
* `unknown` is gated exactly like `mutate`. The whole point of keeping it as a
|
|
211
|
+
* distinct label is that it is not a guess; the gate treats a thing that might
|
|
212
|
+
* be a mutation as a mutation.
|
|
213
|
+
*/
|
|
214
|
+
export function requiresExplicitEditor(cls) {
|
|
215
|
+
return cls !== "read";
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=action-class.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-class.js","sourceRoot":"","sources":["../src/action-class.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Unreal asset path handling (#798).
|
|
3
|
+
*
|
|
4
|
+
* Callers spell an asset path several defensible ways: with a `.uasset`
|
|
5
|
+
* suffix, with the object suffix Unreal prints in the content browser, with
|
|
6
|
+
* backslashes, or wrapped in the `{ refPath }` object reference that the
|
|
7
|
+
* engine's own toolsets use. The bridge wants exactly one of those forms.
|
|
8
|
+
* Repairing the rest at the boundary is cheaper than making every caller
|
|
9
|
+
* discover the rule by trial and error, and a rejection that names the field
|
|
10
|
+
* and shows the accepted shape is cheaper than a generic failure.
|
|
11
|
+
*/
|
|
12
|
+
/** Guidance appended to every path rejection, so one error is enough to fix the call. */
|
|
13
|
+
export declare const PATH_FORMAT_HELP: string;
|
|
14
|
+
/**
|
|
15
|
+
* Fold the accepted spellings of an Unreal asset path into the one form the
|
|
16
|
+
* bridge wants: a long package path, no extension, no object suffix.
|
|
17
|
+
*
|
|
18
|
+
* `/Game/UI/WBP_Foo.uasset` -> `/Game/UI/WBP_Foo`
|
|
19
|
+
* `/Game/UI/WBP_Foo.WBP_Foo` -> `/Game/UI/WBP_Foo`
|
|
20
|
+
* `/Game/UI/WBP_Foo.WBP_Foo_C` -> `/Game/UI/WBP_Foo`
|
|
21
|
+
* `\Game\UI\WBP_Foo` -> `/Game/UI/WBP_Foo`
|
|
22
|
+
* `/Game/UI/` -> rejected (no asset name)
|
|
23
|
+
*
|
|
24
|
+
* Rejects, naming the offending field, what cannot be repaired without
|
|
25
|
+
* guessing: empty values, filesystem paths, and relative paths.
|
|
26
|
+
*/
|
|
27
|
+
export declare function normalizeUnrealAssetPath(raw: unknown, field?: string): string;
|
|
28
|
+
/** Split a normalized package path into the package directory and the asset name. */
|
|
29
|
+
export declare function splitAssetPath(assetPath: string): {
|
|
30
|
+
packagePath: string;
|
|
31
|
+
name: string;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Resolve the destination of a create action from either spelling: the
|
|
35
|
+
* canonical `assetPath` (or its `path` alias), or the older `packagePath`
|
|
36
|
+
* plus `name` pair. Returns the normalized package path.
|
|
37
|
+
*
|
|
38
|
+
* Throws INVALID_PARAMS naming both spellings when neither is usable, so the
|
|
39
|
+
* caller is never told to supply an internal field name it cannot see in the
|
|
40
|
+
* schema.
|
|
41
|
+
*/
|
|
42
|
+
export declare function resolveCreateAssetPath(params: Record<string, unknown>): string;
|
|
43
|
+
/**
|
|
44
|
+
* Pull an asset path out of any value a caller might use for it: a plain
|
|
45
|
+
* string, Unreal's `{ refPath }` object reference (what the wrapped engine
|
|
46
|
+
* toolsets use), or either of those serialized as JSON by a client that
|
|
47
|
+
* flattens object arguments to strings.
|
|
48
|
+
*/
|
|
49
|
+
export declare function coerceAssetPathValue(value: unknown): string | undefined;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { McpError, ErrorCode } from "./errors.js";
|
|
2
|
+
/**
|
|
3
|
+
* Shared Unreal asset path handling (#798).
|
|
4
|
+
*
|
|
5
|
+
* Callers spell an asset path several defensible ways: with a `.uasset`
|
|
6
|
+
* suffix, with the object suffix Unreal prints in the content browser, with
|
|
7
|
+
* backslashes, or wrapped in the `{ refPath }` object reference that the
|
|
8
|
+
* engine's own toolsets use. The bridge wants exactly one of those forms.
|
|
9
|
+
* Repairing the rest at the boundary is cheaper than making every caller
|
|
10
|
+
* discover the rule by trial and error, and a rejection that names the field
|
|
11
|
+
* and shows the accepted shape is cheaper than a generic failure.
|
|
12
|
+
*/
|
|
13
|
+
/** Guidance appended to every path rejection, so one error is enough to fix the call. */
|
|
14
|
+
export const PATH_FORMAT_HELP = "Expected an Unreal package path such as '/Game/UI/WBP_Example'. " +
|
|
15
|
+
"A '.uasset' suffix, an object suffix such as '.WBP_Example', and backslashes are accepted and normalized. " +
|
|
16
|
+
"A filesystem path or a path that does not start with '/' is not.";
|
|
17
|
+
function invalid(message) {
|
|
18
|
+
return new McpError(ErrorCode.INVALID_PARAMS, message);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Fold the accepted spellings of an Unreal asset path into the one form the
|
|
22
|
+
* bridge wants: a long package path, no extension, no object suffix.
|
|
23
|
+
*
|
|
24
|
+
* `/Game/UI/WBP_Foo.uasset` -> `/Game/UI/WBP_Foo`
|
|
25
|
+
* `/Game/UI/WBP_Foo.WBP_Foo` -> `/Game/UI/WBP_Foo`
|
|
26
|
+
* `/Game/UI/WBP_Foo.WBP_Foo_C` -> `/Game/UI/WBP_Foo`
|
|
27
|
+
* `\Game\UI\WBP_Foo` -> `/Game/UI/WBP_Foo`
|
|
28
|
+
* `/Game/UI/` -> rejected (no asset name)
|
|
29
|
+
*
|
|
30
|
+
* Rejects, naming the offending field, what cannot be repaired without
|
|
31
|
+
* guessing: empty values, filesystem paths, and relative paths.
|
|
32
|
+
*/
|
|
33
|
+
export function normalizeUnrealAssetPath(raw, field = "assetPath") {
|
|
34
|
+
if (typeof raw !== "string") {
|
|
35
|
+
throw invalid(`${field} must be a string. ${PATH_FORMAT_HELP}`);
|
|
36
|
+
}
|
|
37
|
+
let value = raw.trim().replace(/\\/g, "/");
|
|
38
|
+
if (value === "") {
|
|
39
|
+
throw invalid(`${field} must not be empty. ${PATH_FORMAT_HELP}`);
|
|
40
|
+
}
|
|
41
|
+
if (/^[A-Za-z]:\//.test(value) || value.startsWith("file:")) {
|
|
42
|
+
throw invalid(`${field} '${raw}' is a filesystem path. ${PATH_FORMAT_HELP}`);
|
|
43
|
+
}
|
|
44
|
+
value = value.replace(/\/{2,}/g, "/");
|
|
45
|
+
while (value.length > 1 && value.endsWith("/"))
|
|
46
|
+
value = value.slice(0, -1);
|
|
47
|
+
if (!value.startsWith("/")) {
|
|
48
|
+
throw invalid(`${field} '${raw}' is not a mount-rooted path. ${PATH_FORMAT_HELP}`);
|
|
49
|
+
}
|
|
50
|
+
// Everything from the first dot of the final segment is an extension or an
|
|
51
|
+
// object suffix. The bridge addresses the package, not the object.
|
|
52
|
+
const cut = value.lastIndexOf("/");
|
|
53
|
+
const dir = value.slice(0, cut);
|
|
54
|
+
let leaf = value.slice(cut + 1);
|
|
55
|
+
const dot = leaf.indexOf(".");
|
|
56
|
+
if (dot >= 0)
|
|
57
|
+
leaf = leaf.slice(0, dot);
|
|
58
|
+
if (leaf === "") {
|
|
59
|
+
throw invalid(`${field} '${raw}' has no asset name. ${PATH_FORMAT_HELP}`);
|
|
60
|
+
}
|
|
61
|
+
const normalized = `${dir}/${leaf}`;
|
|
62
|
+
if (normalized.split("/").filter(Boolean).length < 2) {
|
|
63
|
+
throw invalid(`${field} '${raw}' is missing a mount point. ${PATH_FORMAT_HELP}`);
|
|
64
|
+
}
|
|
65
|
+
return normalized;
|
|
66
|
+
}
|
|
67
|
+
/** Split a normalized package path into the package directory and the asset name. */
|
|
68
|
+
export function splitAssetPath(assetPath) {
|
|
69
|
+
const cut = assetPath.lastIndexOf("/");
|
|
70
|
+
return { packagePath: assetPath.slice(0, cut), name: assetPath.slice(cut + 1) };
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Resolve the destination of a create action from either spelling: the
|
|
74
|
+
* canonical `assetPath` (or its `path` alias), or the older `packagePath`
|
|
75
|
+
* plus `name` pair. Returns the normalized package path.
|
|
76
|
+
*
|
|
77
|
+
* Throws INVALID_PARAMS naming both spellings when neither is usable, so the
|
|
78
|
+
* caller is never told to supply an internal field name it cannot see in the
|
|
79
|
+
* schema.
|
|
80
|
+
*/
|
|
81
|
+
export function resolveCreateAssetPath(params) {
|
|
82
|
+
for (const field of ["assetPath", "path"]) {
|
|
83
|
+
const value = coerceAssetPathValue(params[field]);
|
|
84
|
+
if (value !== undefined)
|
|
85
|
+
return normalizeUnrealAssetPath(value, field);
|
|
86
|
+
}
|
|
87
|
+
const name = typeof params.name === "string" ? params.name.trim() : "";
|
|
88
|
+
const packagePath = typeof params.packagePath === "string" ? params.packagePath.trim() : "";
|
|
89
|
+
if (name !== "" && packagePath !== "") {
|
|
90
|
+
return normalizeUnrealAssetPath(`${packagePath}/${name}`, "packagePath + name");
|
|
91
|
+
}
|
|
92
|
+
throw invalid("Missing required parameter 'assetPath'. " +
|
|
93
|
+
`${PATH_FORMAT_HELP} A 'name' plus 'packagePath' pair is accepted as the same thing.`);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Pull an asset path out of any value a caller might use for it: a plain
|
|
97
|
+
* string, Unreal's `{ refPath }` object reference (what the wrapped engine
|
|
98
|
+
* toolsets use), or either of those serialized as JSON by a client that
|
|
99
|
+
* flattens object arguments to strings.
|
|
100
|
+
*/
|
|
101
|
+
export function coerceAssetPathValue(value) {
|
|
102
|
+
if (typeof value === "string") {
|
|
103
|
+
const trimmed = value.trim();
|
|
104
|
+
if (trimmed.startsWith("{")) {
|
|
105
|
+
try {
|
|
106
|
+
return coerceAssetPathValue(JSON.parse(trimmed));
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return trimmed;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return trimmed === "" ? undefined : trimmed;
|
|
113
|
+
}
|
|
114
|
+
if (value && typeof value === "object") {
|
|
115
|
+
const rec = value;
|
|
116
|
+
for (const key of ["refPath", "assetPath", "path"]) {
|
|
117
|
+
const inner = rec[key];
|
|
118
|
+
if (typeof inner === "string" && inner.trim() !== "")
|
|
119
|
+
return inner.trim();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=asset-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asset-path.js","sourceRoot":"","sources":["../src/asset-path.ts"],"names":[],"mappings":"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"}
|
package/dist/auth-cli.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* `npx ue-mcp auth`
|
|
3
|
+
* `npx ue-mcp auth` - interactive GitHub device-flow auth so feedback(submit)
|
|
4
4
|
* can author issues as the user's real GitHub account.
|
|
5
5
|
*
|
|
6
6
|
* The same flow is offered inside `npx ue-mcp init` when the user opts into
|
package/dist/auth-cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* `npx ue-mcp auth`
|
|
3
|
+
* `npx ue-mcp auth` - interactive GitHub device-flow auth so feedback(submit)
|
|
4
4
|
* can author issues as the user's real GitHub account.
|
|
5
5
|
*
|
|
6
6
|
* The same flow is offered inside `npx ue-mcp init` when the user opts into
|