import * as fs from "node:fs"; import * as path from "node:path"; import { fileURLToPath } from "node:url"; import { SELESAI_CODING_AGENT_PACKAGE_ROOT_ENV } from "../../shared/utils.ts"; export const SELESAI_CODING_AGENT_PACKAGE = "@selesai/code"; export const SELESAI_SUBAGENT_SELESAI_BINARY_ENV = "SELESAI_SUBAGENT_SELESAI_BINARY"; export function findPiPackageRootFromEntry(entryPoint: string): string | undefined { let dir = path.dirname(entryPoint); while (dir !== path.dirname(dir)) { const packageJsonPath = path.join(dir, "package.json"); if (fs.existsSync(packageJsonPath)) { const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8")) as { name?: unknown; }; if (pkg.name === SELESAI_CODING_AGENT_PACKAGE) return dir; } dir = path.dirname(dir); } return undefined; } export function resolveInstalledPiPackageRoot(): string | undefined { try { return findPiPackageRootFromEntry( fileURLToPath(import.meta.resolve(SELESAI_CODING_AGENT_PACKAGE)), ); } catch { return undefined; } } export function resolvePiPackageRoot(entry = process.argv[1]): string | undefined { try { return entry ? findPiPackageRootFromEntry(fs.realpathSync(entry)) : undefined; } catch { // process.argv[1] probing is best-effort; callers can fall back to PATH/package resolution. return undefined; } } /** Resolve only the canonical host entry's local dependency graph, not NODE_PATH/global stores. */ export function resolveHostDependencyPiPackageRoot(entry = process.argv[1]): string | undefined { let canonicalEntry: string; try { if (!entry) return undefined; canonicalEntry = fs.realpathSync(entry); } catch { return undefined; } let dir = path.dirname(canonicalEntry); for (;;) { const root = path.join(dir, "node_modules", SELESAI_CODING_AGENT_PACKAGE); try { fs.lstatSync(root); } catch (error) { // ENOTDIR: a file named node_modules is not a candidate, so keep walking like Node's resolver. const code = (error as NodeJS.ErrnoException).code; if (code !== "ENOENT" && code !== "ENOTDIR") return undefined; const parent = path.dirname(dir); if (parent === dir) return undefined; dir = parent; continue; } // The nearest candidate stays authoritative: a broken link or an unusable manifest is skipped // as not-found instead of resolving a hoisted or extension-owned copy further up the tree. let canonicalRoot: string; try { canonicalRoot = fs.realpathSync(root); } catch { return undefined; } if (!readPiPackageJson(path.join(canonicalRoot, "package.json"))) return undefined; return canonicalRoot; } } /** One SDK root for foreground imports and detached peer aliases. */ export function resolveHostPiPackageRoot(deps: PiSpawnDeps = {}): string | undefined { return selectPiPackage(deps)?.root; } export interface PiSpawnDeps { platform?: NodeJS.Platform; execPath?: string; argv1?: string; bunVersion?: string; existsSync?: (filePath: string) => boolean; realpathSync?: (filePath: string) => string; readFileSync?: (filePath: string, encoding: "utf-8") => string; resolvePackageJson?: () => string; resolvePackageEntry?: () => string; piPackageRoot?: string; env?: NodeJS.ProcessEnv; } /** Compiled Pi's entrypoint is virtual; execPath is the real (possibly renamed) image. */ export function resolveBunPiExecutable(deps: PiSpawnDeps = {}): string | undefined { const bunVersion = deps.bunVersion ?? process.versions.bun; const entry = deps.argv1 ?? process.argv[1]; if (!bunVersion || !entry || !/^(?:\/\$bunfs\/|B:[\\/]~BUN[\\/])/.test(entry)) return undefined; const env = deps.env ?? process.env; return env[SELESAI_SUBAGENT_SELESAI_BINARY_ENV]?.trim() || (deps.execPath ?? process.execPath); } interface PiSpawnCommand { command: string; args: string[]; } interface PiPackageJson { name?: unknown; bin?: string | Record; } function isNodeScriptPath(filePath: string): boolean { return /\.(?:mjs|cjs|js)$/i.test(filePath); } function isRunnableNodeScript( filePath: string, existsSync: (filePath: string) => boolean, ): boolean { if (!existsSync(filePath)) return false; return isNodeScriptPath(filePath); } function normalizePath(filePath: string): string { return path.isAbsolute(filePath) ? filePath : path.resolve(filePath); } function isStandaloneSelesaiExecutable(execPath: string): boolean { const executableName = execPath.split(/[\\/]/).pop(); return /^(?:selesai|selesai-code)(?:\.exe)?$/i.test(executableName ?? ""); } /** Read a candidate manifest, returning undefined for every unusable candidate instead of throwing. */ function readPiPackageJson( packageJsonPath: string, readFileSync: (filePath: string, encoding: "utf-8") => string = (filePath, encoding) => fs.readFileSync(filePath, encoding), ): PiPackageJson | undefined { let source: string; try { source = readFileSync(packageJsonPath, "utf-8"); } catch { return undefined; } let pkg: unknown; try { pkg = JSON.parse(source); } catch { return undefined; } if (!pkg || typeof pkg !== "object" || Array.isArray(pkg)) return undefined; if ((pkg as PiPackageJson).name !== SELESAI_CODING_AGENT_PACKAGE) return undefined; return pkg as PiPackageJson; } interface PiPackageCandidate { root: string; packageJson: PiPackageJson; } type PiPackageSelection = | { root: string; cliScript: string } | PiPackageCandidate; /** Preserve direct JS launches; extensionless .bin/selesai launchers must honor explicit roots first. */ function selectArgvPiCliScript(deps: PiSpawnDeps): { root: string; cliScript: string } | undefined { const existsSync = deps.existsSync ?? fs.existsSync; const realpathSync = deps.realpathSync ?? fs.realpathSync; const argv1 = deps.argv1 ?? process.argv[1]; if (!argv1) return undefined; const argvPath = normalizePath(argv1); if (!isRunnableNodeScript(argvPath, existsSync)) return undefined; try { const canonicalArgvPath = realpathSync(argvPath); const root = isRunnableNodeScript(canonicalArgvPath, existsSync) ? findPiPackageRootFromEntry(canonicalArgvPath) : undefined; return root ? { root, cliScript: canonicalArgvPath } : undefined; } catch { // Ownership probing is best-effort; an unverified host entry is not a Pi CLI. return undefined; } } /** Authoritative host roots, in upstream precedence: explicit, env, running entry, host dependency. */ function* authoritativePiPackageCandidates(deps: PiSpawnDeps): Generator { const argv1 = deps.argv1 ?? process.argv[1]; const env = deps.env ?? process.env; const roots: Array<() => string | undefined> = [ () => deps.piPackageRoot?.trim() || undefined, () => env[SELESAI_CODING_AGENT_PACKAGE_ROOT_ENV]?.trim() || undefined, () => resolvePiPackageRoot(argv1), () => resolveHostDependencyPiPackageRoot(argv1), ]; for (const candidateRoot of roots) { const root = candidateRoot(); if (!root) continue; const packageJson = readPiPackageJson(path.join(root, "package.json"), deps.readFileSync); if (packageJson) yield { root, packageJson }; } } /** Only extension-relative discovery is best-effort, for both SDK and CLI consumers. */ function extensionPiPackageCandidates(deps: PiSpawnDeps): PiPackageCandidate[] { const packageJsonCandidates: Array<() => string | undefined> = []; if (deps.resolvePackageJson) packageJsonCandidates.push(deps.resolvePackageJson); packageJsonCandidates.push(() => { const packageRoot = deps.resolvePackageEntry ? findPiPackageRootFromEntry(deps.resolvePackageEntry()) : resolveInstalledPiPackageRoot(); return packageRoot ? path.join(packageRoot, "package.json") : undefined; }); const candidates: PiPackageCandidate[] = []; for (const candidatePackageJson of packageJsonCandidates) { try { const packageJsonPath = candidatePackageJson(); if (!packageJsonPath) continue; const packageJson = readPiPackageJson(packageJsonPath, deps.readFileSync); if (packageJson) candidates.push({ root: path.dirname(packageJsonPath), packageJson }); } catch { // No authoritative host root was found; keep probing the extension install. } } return candidates; } /** Select the host SDK root; an unusable candidate is skipped so a later candidate can still resolve. */ function selectPiPackage(deps: PiSpawnDeps): PiPackageSelection | undefined { const argvSelection = selectArgvPiCliScript(deps); if (argvSelection) return argvSelection; for (const candidate of authoritativePiPackageCandidates(deps)) return candidate; for (const candidate of extensionPiPackageCandidates(deps)) return candidate; return undefined; } function candidateCliScript( candidate: PiPackageCandidate, existsSync: (filePath: string) => boolean, ): string | undefined { const binField = candidate.packageJson.bin; const binPath = typeof binField === "string" ? binField : (binField?.selesai ?? Object.values(binField ?? {})[0]); const cli = binPath ? path.resolve(candidate.root, binPath) : undefined; return cli && isRunnableNodeScript(cli, existsSync) ? cli : undefined; } export function resolvePiCliScript(deps: PiSpawnDeps = {}): string | undefined { const argvSelection = selectArgvPiCliScript(deps); if (argvSelection) return argvSelection.cliScript; const existsSync = deps.existsSync ?? fs.existsSync; // A selected root without a runnable CLI script is skipped for the CLI path only; the SDK root stays selected. for (const candidate of authoritativePiPackageCandidates(deps)) { const cli = candidateCliScript(candidate, existsSync); if (cli) return cli; } // Probing the extension install is deferred until no authoritative root supplied a CLI. for (const candidate of extensionPiPackageCandidates(deps)) { const cli = candidateCliScript(candidate, existsSync); if (cli) return cli; } return undefined; } export function getPiSpawnCommand( args: string[], deps: PiSpawnDeps = {}, ): PiSpawnCommand { const platform = deps.platform ?? process.platform; const env = deps.env ?? process.env; const selesaiBinary = env[SELESAI_SUBAGENT_SELESAI_BINARY_ENV]?.trim(); if (selesaiBinary) { if (platform === "win32" && isNodeScriptPath(selesaiBinary)) { return { command: deps.execPath ?? process.execPath, args: [selesaiBinary, ...args], }; } return { command: selesaiBinary, args }; } const execPath = deps.execPath ?? process.execPath; if (isStandaloneSelesaiExecutable(execPath)) { return { command: execPath, args }; } const piCliPath = resolvePiCliScript(deps); if (piCliPath) { return { command: execPath, args: [piCliPath, ...args], }; } if (platform === "win32") { throw new Error( `Could not resolve the Pi CLI on Windows. Set ${SELESAI_SUBAGENT_SELESAI_BINARY_ENV} or ensure ${SELESAI_CODING_AGENT_PACKAGE} is installed.`, ); } return { command: "selesai", args }; }