fix(runner): fix uvx variable scoping bug
Some checks failed
CI / Lint (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Broker tests (Postgres) (push) Has been cancelled
CI / Docker build (linux/amd64) (push) Has been cancelled

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-04-08 15:33:51 +01:00
parent 17e6361d64
commit 45505a1635

View File

@@ -259,27 +259,27 @@ const server = createServer(async (req, res) => {
return json(res, 500, { error: `uvx install failed: ${e.message}` }); return json(res, 500, { error: `uvx install failed: ${e.message}` });
} }
// Find the MCP binary in the venv // Find the MCP binary in the venv
let uvxBinPath = null;
const venvBin = join(svcSourcePath, ".venv/bin"); const venvBin = join(svcSourcePath, ".venv/bin");
if (existsSync(venvBin)) { if (existsSync(venvBin)) {
const bins = readdirSync(venvBin).filter(b => !["python", "python3", "pip", "pip3", "activate", "Activate.ps1", "activate.csh", "activate.fish", "deactivate"].includes(b) && !b.startsWith("python3.")); const bins = readdirSync(venvBin).filter(b => !["python", "python3", "pip", "pip3", "activate", "Activate.ps1", "activate.csh", "activate.fish", "deactivate"].includes(b) && !b.startsWith("python3."));
const pkgShort = body.uvxPackage.split("/").pop().replace(/^@/, ""); const pkgShort = body.uvxPackage.split("/").pop().replace(/^@/, "");
const match = bins.find(b => b.includes(pkgShort.replace(/-/g, ""))) || bins.find(b => b.includes("mcp")) || bins[0]; const match = bins.find(b => b.includes(pkgShort.replace(/-/g, ""))) || bins.find(b => b.includes("mcp")) || bins[0];
if (match) svc._npxBin = join(venvBin, match); if (match) uvxBinPath = join(venvBin, match);
} }
svcRuntime = "python"; svcRuntime = "python";
// Skip normal installDeps — already installed via uv // Skip normal installDeps — already installed via uv
const svc2 = { name, sourcePath: svcSourcePath, runtime: svcRuntime, env: svcEnv || {}, process: null, pid: null, tools: [], status: "running", pending: new Map(), logs: [], restarts: 0, healthFailures: 0, _npxBin: svc?._npxBin }; const svc2 = { name, sourcePath: svcSourcePath, runtime: svcRuntime, env: svcEnv || {}, process: null, pid: null, tools: [], status: "running", pending: new Map(), logs: [], restarts: 0, healthFailures: 0, _npxBin: uvxBinPath };
Object.assign(svc, svc2); services.set(name, svc2);
services.set(name, svc); spawnService(svc2);
spawnService(svc);
await new Promise(r => setTimeout(r, 1500)); await new Promise(r => setTimeout(r, 1500));
try { try {
svc.tools = await initMcp(svc); svc2.tools = await initMcp(svc2);
console.log(`[runner] ${name} ready (uvx), ${svc.tools.length} tools`); console.log(`[runner] ${name} ready (uvx), ${svc2.tools.length} tools`);
return json(res, 200, { status: "running", tools: svc.tools }); return json(res, 200, { status: "running", tools: svc2.tools });
} catch (e) { } catch (e) {
svc.status = "failed"; svc.logs.push(`MCP init failed: ${e.message}`); svc2.status = "failed"; svc2.logs.push(`MCP init failed: ${e.message}`);
return json(res, 500, { error: e.message, logs: svc.logs.slice(-10) }); return json(res, 500, { error: e.message, logs: svc2.logs.slice(-10) });
} }
} else if (!svcSourcePath) { } else if (!svcSourcePath) {
return json(res, 400, { error: "one of sourcePath, gitUrl, or npxPackage required" }); return json(res, 400, { error: "one of sourcePath, gitUrl, or npxPackage required" });