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>
36 lines
1.5 KiB
JavaScript
36 lines
1.5 KiB
JavaScript
import { test } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { buildApplyCommand, parseResultEnvelope, _internal } from "../src/pythonGen.js";
|
|
|
|
test("pyRepr escapes quotes, backslashes and newlines", () => {
|
|
const r = _internal.pyRepr(`a'b\\c\nd`);
|
|
assert.equal(r, `'a\\'b\\\\c\\nd'`);
|
|
});
|
|
|
|
test("buildApplyCommand emits importable bootstrap and embeds payload", () => {
|
|
const graph = { bp_path: "/Game/X", nodes: [{ id: "n1", kind: "branch" }] };
|
|
const cmd = buildApplyCommand(graph);
|
|
assert.match(cmd, /import sys, json/);
|
|
assert.match(cmd, /apply_graph\.entrypoint\(/);
|
|
assert.match(cmd, /__MCP_RESULT__/);
|
|
// Payload must survive as a python literal that, when eval'd, equals our JSON.
|
|
const m = /apply_graph\.entrypoint\(('.*?')\)/s.exec(cmd);
|
|
assert.ok(m, "no payload found in command");
|
|
// Roughly verify: drop quotes & unescape single-quote/backslash and compare JSON.
|
|
const lit = m[1].slice(1, -1).replace(/\\'/g, "'").replace(/\\\\/g, "\\")
|
|
.replace(/\\n/g, "\n").replace(/\\r/g, "\r").replace(/\\t/g, "\t");
|
|
assert.deepEqual(JSON.parse(lit), graph);
|
|
});
|
|
|
|
test("parseResultEnvelope extracts JSON between markers", () => {
|
|
const stdout = "noise\n__MCP_RESULT__" + JSON.stringify({ ok: true, spawned: { a: "K2N_1" } }) + "__MCP_END__\nmore noise";
|
|
const r = parseResultEnvelope(stdout);
|
|
assert.equal(r.ok, true);
|
|
assert.equal(r.spawned.a, "K2N_1");
|
|
});
|
|
|
|
test("parseResultEnvelope errors on missing envelope", () => {
|
|
const r = parseResultEnvelope("no envelope here");
|
|
assert.equal(r.ok, false);
|
|
});
|