fix: harden pi package resolution
parent
5a1687484c
commit
41dd3b11b7
|
|
@ -1,26 +1,73 @@
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import { createRequire } from "node:module";
|
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
// Resolve the bundled pi/tau binary path from the installed dependency.
|
// Resolve the bundled pi/tau binary path from the installed dependency.
|
||||||
export function resolveBundledPiBinary(): string | null {
|
export function resolveBundledPiBinary(): string | null {
|
||||||
|
const candidatePkgDirs: string[] = [];
|
||||||
|
|
||||||
|
// Preferred: ESM resolution to the package entry, then walk up to package.json.
|
||||||
try {
|
try {
|
||||||
const require = createRequire(import.meta.url);
|
const resolved = (import.meta as { resolve?: (s: string) => string })
|
||||||
const pkgPath = require.resolve(
|
.resolve;
|
||||||
"@mariozechner/pi-coding-agent/package.json",
|
const entryUrl = resolved?.("@mariozechner/pi-coding-agent");
|
||||||
);
|
if (typeof entryUrl === "string" && entryUrl.startsWith("file:")) {
|
||||||
const pkgDir = path.dirname(pkgPath);
|
const entryPath = fileURLToPath(entryUrl);
|
||||||
// Prefer compiled binary if present, else fall back to dist/cli.js (has shebang).
|
let dir = path.dirname(entryPath);
|
||||||
const binCandidates = [
|
for (let i = 0; i < 12; i += 1) {
|
||||||
path.join(pkgDir, "dist", "pi"),
|
const pkgJson = path.join(dir, "package.json");
|
||||||
path.join(pkgDir, "dist", "cli.js"),
|
if (fs.existsSync(pkgJson)) {
|
||||||
path.join(pkgDir, "bin", "tau-dev.mjs"),
|
candidatePkgDirs.push(dir);
|
||||||
];
|
break;
|
||||||
for (const candidate of binCandidates) {
|
}
|
||||||
if (fs.existsSync(candidate)) return candidate;
|
const parent = path.dirname(dir);
|
||||||
|
if (parent === dir) break;
|
||||||
|
dir = parent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// Dependency missing or resolution failed.
|
// ignore; we'll try filesystem fallbacks below
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: walk up from this module's directory to find node_modules.
|
||||||
|
try {
|
||||||
|
let dir = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
for (let i = 0; i < 12; i += 1) {
|
||||||
|
candidatePkgDirs.push(
|
||||||
|
path.join(dir, "node_modules", "@mariozechner", "pi-coding-agent"),
|
||||||
|
);
|
||||||
|
const parent = path.dirname(dir);
|
||||||
|
if (parent === dir) break;
|
||||||
|
dir = parent;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: assume CWD is project root.
|
||||||
|
candidatePkgDirs.push(
|
||||||
|
path.resolve(
|
||||||
|
process.cwd(),
|
||||||
|
"node_modules",
|
||||||
|
"@mariozechner",
|
||||||
|
"pi-coding-agent",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const pkgDir of candidatePkgDirs) {
|
||||||
|
try {
|
||||||
|
if (!fs.existsSync(pkgDir)) continue;
|
||||||
|
const binCandidates = [
|
||||||
|
path.join(pkgDir, "dist", "pi"),
|
||||||
|
path.join(pkgDir, "dist", "cli.js"),
|
||||||
|
path.join(pkgDir, "bin", "tau-dev.mjs"),
|
||||||
|
];
|
||||||
|
for (const candidate of binCandidates) {
|
||||||
|
if (fs.existsSync(candidate)) return candidate;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// ignore this candidate
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,8 @@ function safeReadJson(filePath: string): Record<string, unknown> | null {
|
||||||
if (!exists(filePath)) return null;
|
if (!exists(filePath)) return null;
|
||||||
const raw = fs.readFileSync(filePath, "utf-8");
|
const raw = fs.readFileSync(filePath, "utf-8");
|
||||||
const parsed = JSON.parse(raw) as unknown;
|
const parsed = JSON.parse(raw) as unknown;
|
||||||
if (typeof parsed !== "object" || parsed === null) return null;
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
|
||||||
|
return null;
|
||||||
return parsed as Record<string, unknown>;
|
return parsed as Record<string, unknown>;
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue