import type { ProjectContext } from "./project.js"; export interface DeployResult { pythonPluginEnabled: boolean; cppPluginDeployed: boolean; cppPluginEnabled: boolean; error?: string; } export interface AttachResult { pythonPluginEnabled: boolean; cppPluginEnabled: boolean; cppPluginPresent: boolean; packagedVersion: string | null; installedVersion: string | null; versionMatch: boolean | null; error?: string; } /** * Deploy the C++ bridge plugin to the target UE project. * * Copies plugin source from plugin/ue_mcp_bridge/ into the target * project's Plugins/UE_MCP_Bridge/ directory (skipping build artifacts). * Also enables PythonScriptPlugin in the .uproject because the C++ * bridge's `execute_python` handler calls into it at runtime. */ export declare function deploy(context: ProjectContext): DeployResult; export declare function deploySummary(r: DeployResult): string; /** * Non-destructive attach used on normal MCP server startup. * * Unlike `deploy()`, this NEVER overwrites bridge source under * `Plugins/UE_MCP_Bridge/Source/` - so local forks/edits and * project-tracked bridge revisions are preserved. It only: * - detects whether the bridge plugin is installed in the project * - ensures PythonScriptPlugin is listed in the .uproject * - ensures UE_MCP_Bridge is listed in the .uproject * - reports plugin presence + version for a warning-level check * * Detection comes first, and a project without the plugin installed is * left byte-identical. Enabling a plugin that is not on disk turns the * project's next launch in Unreal into a missing-plugin prompt, and * PythonScriptPlugin is only enabled here because the bridge's * `execute_python` handler needs it, so it has no reason to be written * into a project the bridge is absent from. * * If the plugin is missing or a version mismatch is detected, callers * should surface that to the user and ask them to run `ue-mcp init` * or `ue-mcp deploy` explicitly. */ export declare function attach(context: ProjectContext): AttachResult; export declare function attachSummary(r: AttachResult): string; /** * Which entries in the deployed tree are stale, given what the source has. * * Exported so the mirror rule can be tested as the rule rather than as a copy * of it. "Never hand-copy a file into the test project" is a property of this * function: anything the source does not name, and that is not a build * artifact directory, is removed on the next deploy, so a hand-placed file * never survives to be compiled. * * Name comparison follows the filesystem. On Windows and macOS `Handlers.cpp` * and `handlers.cpp` are one file, and treating them as two deletes the file * that was just copied in. */ export declare function staleDeployedEntries(destNames: string[], sourceNames: Set, artifactDirs: Set, caseInsensitiveFs?: boolean): string[]; /** * Copy the authored plugin tree over the deployed one, and leave the deployed * tree in a state UnrealBuildTool will compile correctly. * * Exported with both directories as arguments so the whole step, including the * Build.cs touch that a new source file depends on, can be driven against real * directories. deployCppPlugin resolves the authored tree relative to this * module, which no test can redirect. */ export declare function deployPluginTree(sourcePluginDir: string, targetPluginDir: string): boolean; /** * Make UnrealBuildTool rescan a module whose file list just changed. * * UBT caches the source list per module and rebuilds it only when the module's * Build.cs is newer than that cache. A new .cpp therefore deploys, compiles * into nothing, and every action in it answers "Unknown method" at runtime, * from a build that reported success. Touching every Build.cs under the * deployed plugin costs nothing on a build where no file was added, because * this only runs when one was. */ export declare function touchBuildRules(pluginDir: string, because?: string[]): string[]; export declare function findEngineInstall(engineAssociation: string | null): string | null;