ai agent
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
// Probe: which Node APIs does the VS Code Electron binary provide in
|
||||
// ELECTRON_RUN_AS_NODE mode? Run with:
|
||||
// ELECTRON_RUN_AS_NODE=1 "<Code.exe>" probe.cjs
|
||||
const out = {};
|
||||
|
||||
try {
|
||||
out.nodeVersion = process.versions.node;
|
||||
out.electronVersion = process.versions.electron ?? null;
|
||||
out.isElectronRunAsNode = process.env.ELECTRON_RUN_AS_NODE === "1";
|
||||
out.execPath = process.execPath;
|
||||
out.platform = process.platform;
|
||||
} catch (e) {
|
||||
out.baseError = String(e);
|
||||
}
|
||||
|
||||
const modules = [
|
||||
"node:fs",
|
||||
"node:fs/promises",
|
||||
"node:path",
|
||||
"node:os",
|
||||
"node:http",
|
||||
"node:readline",
|
||||
"node:zlib",
|
||||
"node:crypto",
|
||||
"node:util",
|
||||
"node:net",
|
||||
"node:child_process",
|
||||
"node:test",
|
||||
"node:assert",
|
||||
"node:url",
|
||||
"node:events",
|
||||
];
|
||||
out.modules = {};
|
||||
for (const m of modules) {
|
||||
try {
|
||||
require(m);
|
||||
out.modules[m] = "ok";
|
||||
} catch (e) {
|
||||
out.modules[m] = "FAIL: " + (e && e.code ? e.code : String(e));
|
||||
}
|
||||
}
|
||||
|
||||
// The APIs the MCP server actually depends on.
|
||||
try {
|
||||
const { parseLoadedXml } = require("../out/agent/forwardRefs.js");
|
||||
const parsed = parseLoadedXml('<AssetDeclaration xmlns="uri:ea.com:eala:asset"><GameObject id="X"/></AssetDeclaration>');
|
||||
out.forwardRefs = "ok: elements=" + parsed.parse.elements.length;
|
||||
} catch (e) {
|
||||
out.forwardRefs = "FAIL: " + String(e).slice(0, 160);
|
||||
}
|
||||
|
||||
try {
|
||||
const { startLocalServer } = require("../out/agent/localServer.js");
|
||||
out.localServer = typeof startLocalServer === "function" ? "loadable" : "missing";
|
||||
} catch (e) {
|
||||
out.localServer = "FAIL: " + String(e).slice(0, 160);
|
||||
}
|
||||
|
||||
// Async smoke test: gzip round-trip + http listen (both used at runtime).
|
||||
(async () => {
|
||||
try {
|
||||
const { gzip, gunzip } = require("node:zlib");
|
||||
const { promisify } = require("node:util");
|
||||
const buf = await promisify(gzip)(Buffer.from("hello"));
|
||||
const back = await promisify(gunzip)(buf);
|
||||
out.zlibRoundTrip = back.toString() === "hello" ? "ok" : "mismatch";
|
||||
} catch (e) {
|
||||
out.zlibRoundTrip = "FAIL: " + String(e).slice(0, 120);
|
||||
}
|
||||
|
||||
try {
|
||||
const { startLocalServer } = require("../out/agent/localServer.js");
|
||||
const handle = await startLocalServer({
|
||||
getIndex: () => null,
|
||||
listProjects: () => [],
|
||||
token: "probe",
|
||||
});
|
||||
const res = await fetch(`http://127.0.0.1:${handle.port}/status`, {
|
||||
headers: { authorization: "Bearer probe" },
|
||||
});
|
||||
const body = await res.json();
|
||||
out.httpServer = "ok: " + JSON.stringify(body);
|
||||
await handle.close();
|
||||
} catch (e) {
|
||||
out.httpServer = "FAIL: " + String(e).slice(0, 160);
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(out, null, 2));
|
||||
})();
|
||||
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* Starts a real local live-index server with a fake in-memory index and
|
||||
* registers it exactly like the extension does (instance file + per-project
|
||||
* endpoint + merged manifest). Used by the integration smoke test.
|
||||
*
|
||||
* Prints the agent home as its first stdout line, then stays alive.
|
||||
*/
|
||||
const { startLocalServer } = require("../out/agent/localServer.js");
|
||||
const { writeInstance, writeManifest } = require("../out/agent/instances.js");
|
||||
const { writeEndpoint, writeEndpointForProject } = require("../out/agent/endpoint.js");
|
||||
const { mkdirSync, writeFileSync } = require("node:fs");
|
||||
const { join } = require("node:path");
|
||||
|
||||
const PROJECT = process.env.RA3_PROJECT || "D:/Mods/Alpha";
|
||||
const OTHER = "D:/Mods/Beta";
|
||||
// The agent home is passed in, so the caller knows it without reading stdout.
|
||||
const home = process.argv[2];
|
||||
if (!home) {
|
||||
console.error("usage: serve-fake-index.cjs <agentHome>");
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
function def(type, id, file, line) {
|
||||
return { type, id, file, line, origin: "project", stream: "static" };
|
||||
}
|
||||
|
||||
const unitFile = `${PROJECT}/Data/AthenaCannon.xml`;
|
||||
const unit = def("GameObject", "AthenaCannon", unitFile, 2);
|
||||
const weapon = def("WeaponTemplate", "AthenaCannonWeapon", `${PROJECT}/Data/Weapon.xml`, 88);
|
||||
|
||||
const index = {
|
||||
projectDir: PROJECT,
|
||||
sdkDir: "",
|
||||
complete: true,
|
||||
phase: "art",
|
||||
stale: false,
|
||||
assets: new Map([
|
||||
["GameObject", new Map([["athenacannon", [unit]]])],
|
||||
["WeaponTemplate", new Map([["athenacannonweapon", [weapon]]])],
|
||||
]),
|
||||
assetsById: new Map([
|
||||
["athenacannon", [unit]],
|
||||
["athenacannonweapon", [weapon]],
|
||||
]),
|
||||
defines: new Map([["d", [{ name: "D", value: "1", file: unitFile, line: 1, origin: "project" }]]]),
|
||||
files: new Map(),
|
||||
streams: [{ name: "static", entry: `${PROJECT}/Data/Mod.xml`, files: new Set([unitFile.toLowerCase().replace(/\\/g, "/")]) }],
|
||||
manifests: new Map(),
|
||||
sourceCandidates: [],
|
||||
diagnostics: [],
|
||||
references: new Map([
|
||||
[`GameObject\u0000athenacannon\u0000${unitFile}\u00002`, [{ file: `${PROJECT}/Data/Other.xml`, line: 3, start: 1, end: 2, kind: "attr" }]],
|
||||
]),
|
||||
recordsHashes: new Map(),
|
||||
stats: {
|
||||
projectDir: PROJECT, sdkDir: "", phase: "art", complete: true,
|
||||
indexedFiles: 2, parsedFiles: 2, shallowScannedFiles: 0, deferredArtFiles: 0,
|
||||
shallowCacheHits: 0, recordsCacheHits: 0, resolveCacheHits: 0, resolveCalls: 0,
|
||||
snapshotHits: 0, snapshotFallbacks: 0, candidatesMs: 0, walkMs: 0, artScanMs: 0,
|
||||
assetCount: 2, referenceCount: 1, defineCount: 1, manifestFiles: 0,
|
||||
manifestAssetCount: 0, streams: 1, sourceCandidates: 0, elapsedMs: 1,
|
||||
},
|
||||
};
|
||||
|
||||
(async () => {
|
||||
mkdirSync(home, { recursive: true });
|
||||
const handle = await startLocalServer({
|
||||
getIndex: (projectDir) => (!projectDir || projectDir === PROJECT ? index : null),
|
||||
listProjects: () => [PROJECT, OTHER],
|
||||
loadFile: async () => null,
|
||||
});
|
||||
const endpoint = {
|
||||
instanceId: "smoke-1",
|
||||
url: `http://127.0.0.1:${handle.port}`,
|
||||
token: handle.token,
|
||||
projectDir: PROJECT,
|
||||
projects: [PROJECT, OTHER],
|
||||
processId: process.pid,
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
await writeEndpointForProject(PROJECT, { ...endpoint, projectDir: PROJECT }, home);
|
||||
await writeEndpoint(endpoint, home);
|
||||
await writeInstance(endpoint, home);
|
||||
await writeManifest([endpoint], home);
|
||||
// Signal readiness through a file so the caller never has to parse stdout.
|
||||
writeFileSync(join(home, "READY"), `${handle.port}\n`);
|
||||
// Stay alive until killed.
|
||||
setInterval(() => {}, 1 << 30);
|
||||
})();
|
||||
Reference in New Issue
Block a user