Merge of the two project copies into one self-contained plugin (the superset: variable_op + variables.py, full pcg_op runtime/declarative/preset ops, the CreateWidgetFloatAnimation widget tool, and full Voxel graph authoring). Made fully project- and machine-agnostic — no hardcoded paths: - New src/projectPaths.js auto-detects the host .uproject (walk-up), project name, Editor build target, log file, and engine install (EngineAssociation via launcher manifest/registry, else installed-engine scan). All overridable via UE_* env vars. - Rewired buildOrchestrator/insights/launcher/insightsExporter/server.js and the Python workers (cpp_scaffold, live_coding, apply_graph, console) off the old C:/Github/ihy, IHY*, E:/UE_Versions and UE_5.7 literals onto the resolver. - Voxel made optional: Build.cs auto-detects the Voxel plugin (env UE_MCP_WITH_VOXEL override) and the C++ compiles to stubs under WITH_MCP_VOXEL, so the module builds in projects without Voxel; .uplugin marks Voxel optional. - De-branded the agent-gateway and docs; scrubbed a leaked API key; excluded node_modules/Binaries/Intermediate/__pycache__/secrets from the repo. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
61 lines
2.2 KiB
JavaScript
61 lines
2.2 KiB
JavaScript
// Spin up a fake Remote Control endpoint and verify the bridge talks to it.
|
|
import { test } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import http from "node:http";
|
|
import { executePythonInUE, ping } from "../src/ueBridge.js";
|
|
|
|
function startMockUE() {
|
|
const seen = { calls: [] };
|
|
const srv = http.createServer((req, res) => {
|
|
let body = "";
|
|
req.on("data", c => body += c);
|
|
req.on("end", () => {
|
|
if (req.url === "/remote/info" && req.method === "GET") {
|
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
return res.end(JSON.stringify({ name: "MockUE", version: "5.7" }));
|
|
}
|
|
if (req.url === "/remote/object/call" && req.method === "PUT") {
|
|
let parsed = null;
|
|
try { parsed = JSON.parse(body); } catch {}
|
|
seen.calls.push(parsed);
|
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
return res.end(JSON.stringify({ ReturnValue: true }));
|
|
}
|
|
res.writeHead(404); res.end();
|
|
});
|
|
});
|
|
return new Promise(resolve => {
|
|
srv.listen(0, "127.0.0.1", () => {
|
|
const { port } = srv.address();
|
|
resolve({ srv, seen, baseUrl: `http://127.0.0.1:${port}` });
|
|
});
|
|
});
|
|
}
|
|
|
|
test("ping reaches mock UE", async () => {
|
|
const { srv, baseUrl } = await startMockUE();
|
|
try {
|
|
const r = await ping({ baseUrl, timeoutMs: 2000 });
|
|
assert.equal(r.ok, true);
|
|
assert.equal(r.info.name, "MockUE");
|
|
} finally { srv.close(); }
|
|
});
|
|
|
|
test("executePythonInUE PUTs the right payload to /remote/object/call", async () => {
|
|
const { srv, seen, baseUrl } = await startMockUE();
|
|
try {
|
|
const r = await executePythonInUE("print('hi')", { baseUrl, timeoutMs: 2000 });
|
|
assert.equal(r.ok, true);
|
|
assert.equal(seen.calls.length, 1);
|
|
assert.equal(seen.calls[0].functionName, "ExecutePythonCommand");
|
|
assert.equal(seen.calls[0].parameters.PythonCommand, "print('hi')");
|
|
assert.ok(seen.calls[0].objectPath.includes("PythonScriptLibrary"));
|
|
} finally { srv.close(); }
|
|
});
|
|
|
|
test("executePythonInUE returns ok:false when UE unreachable", async () => {
|
|
const r = await executePythonInUE("print('x')", { baseUrl: "http://127.0.0.1:1", timeoutMs: 500 });
|
|
assert.equal(r.ok, false);
|
|
assert.match(r.error, /cannot reach UE/);
|
|
});
|