{"version":3,"file":"pi-spawn.d.ts","sourceRoot":"","sources":["../../../../src/runs/shared/pi-spawn.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,uBAAuB,8BAA8B,CAAC;AACnE,eAAO,MAAM,yBAAyB,0BAA0B,CAAC;AAEjE,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAajF;AAED,wBAAgB,6BAA6B,IAAI,MAAM,GAAG,SAAS,CAElE;AAED,wBAAgB,oBAAoB,IAAI,MAAM,GAAG,SAAS,CAQzD;AAED,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IAC3C,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;IAC5C,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,MAAM,CAAC;IAC/D,kBAAkB,CAAC,EAAE,MAAM,MAAM,CAAC;IAClC,mBAAmB,CAAC,EAAE,MAAM,MAAM,CAAC;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACxB;AAED,UAAU,cAAc;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CACf;AAgBD,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,WAAgB,GAAG,MAAM,GAAG,SAAS,CAiD7E;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,GAAE,WAAgB,GAAG,cAAc,CAqBxF","sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport const PI_CODING_AGENT_PACKAGE = \"@lpb-work/pi-coding-agent\";\nexport const PI_SUBAGENT_PI_BINARY_ENV = \"PI_SUBAGENT_PI_BINARY\";\n\nexport function findPiPackageRootFromEntry(entryPoint: string): string | undefined {\n\tlet dir = path.dirname(entryPoint);\n\twhile (dir !== path.dirname(dir)) {\n\t\tconst packageJsonPath = path.join(dir, \"package.json\");\n\t\tif (fs.existsSync(packageJsonPath)) {\n\t\t\tconst pkg = JSON.parse(fs.readFileSync(packageJsonPath, \"utf-8\")) as {\n\t\t\t\tname?: unknown;\n\t\t\t};\n\t\t\tif (pkg.name === PI_CODING_AGENT_PACKAGE) return dir;\n\t\t}\n\t\tdir = path.dirname(dir);\n\t}\n\treturn undefined;\n}\n\nexport function resolveInstalledPiPackageRoot(): string | undefined {\n\treturn findPiPackageRootFromEntry(fileURLToPath(import.meta.resolve(PI_CODING_AGENT_PACKAGE)));\n}\n\nexport function resolvePiPackageRoot(): string | undefined {\n\ttry {\n\t\tconst entry = process.argv[1];\n\t\treturn entry ? findPiPackageRootFromEntry(fs.realpathSync(entry)) : undefined;\n\t} catch {\n\t\t// process.argv[1] probing is best-effort; callers can fall back to PATH/package resolution.\n\t\treturn undefined;\n\t}\n}\n\nexport interface PiSpawnDeps {\n\tplatform?: NodeJS.Platform;\n\texecPath?: string;\n\targv1?: string;\n\texistsSync?: (filePath: string) => boolean;\n\trealpathSync?: (filePath: string) => string;\n\treadFileSync?: (filePath: string, encoding: \"utf-8\") => string;\n\tresolvePackageJson?: () => string;\n\tresolvePackageEntry?: () => string;\n\tpiPackageRoot?: string;\n\tenv?: NodeJS.ProcessEnv;\n}\n\ninterface PiSpawnCommand {\n\tcommand: string;\n\targs: string[];\n}\n\nfunction isRunnableNodeScript(filePath: string, existsSync: (filePath: string) => boolean): boolean {\n\tif (!existsSync(filePath)) return false;\n\treturn /\\.(?:mjs|cjs|js)$/i.test(filePath);\n}\n\nfunction normalizePath(filePath: string): string {\n\treturn path.isAbsolute(filePath) ? filePath : path.resolve(filePath);\n}\n\nfunction isStandalonePiExecutable(execPath: string): boolean {\n\tconst executableName = execPath.split(/[\\\\/]/).pop();\n\treturn /^pi(?:\\.exe)?$/i.test(executableName ?? \"\");\n}\n\nexport function resolvePiCliScript(deps: PiSpawnDeps = {}): string | undefined {\n\tconst existsSync = deps.existsSync ?? fs.existsSync;\n\tconst realpathSync = deps.realpathSync ?? fs.realpathSync;\n\tconst readFileSync = deps.readFileSync ?? ((filePath, encoding) => fs.readFileSync(filePath, encoding));\n\tconst argv1 = deps.argv1 ?? process.argv[1];\n\n\tif (argv1) {\n\t\tconst argvPath = normalizePath(argv1);\n\t\tif (isRunnableNodeScript(argvPath, existsSync)) {\n\t\t\ttry {\n\t\t\t\tconst canonicalArgvPath = realpathSync(argvPath);\n\t\t\t\tif (isRunnableNodeScript(canonicalArgvPath, existsSync) && findPiPackageRootFromEntry(canonicalArgvPath)) {\n\t\t\t\t\treturn canonicalArgvPath;\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Host package metadata is untrusted here; keep resolving the installed Pi CLI.\n\t\t\t}\n\t\t}\n\t}\n\n\ttry {\n\t\tconst resolvePackageJson =\n\t\t\tdeps.resolvePackageJson ??\n\t\t\t(() => {\n\t\t\t\tconst root = deps.piPackageRoot ?? resolvePiPackageRoot();\n\t\t\t\tif (root) return path.join(root, \"package.json\");\n\t\t\t\tconst packageRoot = deps.resolvePackageEntry\n\t\t\t\t\t? findPiPackageRootFromEntry(deps.resolvePackageEntry())\n\t\t\t\t\t: resolveInstalledPiPackageRoot();\n\t\t\t\tif (!packageRoot) throw new Error(`Could not resolve ${PI_CODING_AGENT_PACKAGE} package root`);\n\t\t\t\treturn path.join(packageRoot, \"package.json\");\n\t\t\t});\n\t\tconst packageJsonPath = resolvePackageJson();\n\t\tconst packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\")) as {\n\t\t\tbin?: string | Record<string, string>;\n\t\t};\n\t\tconst binField = packageJson.bin;\n\t\tconst binPath = typeof binField === \"string\" ? binField : (binField?.pi ?? Object.values(binField ?? {})[0]);\n\t\tif (!binPath) return undefined;\n\t\tconst candidate = path.resolve(path.dirname(packageJsonPath), binPath);\n\t\tif (isRunnableNodeScript(candidate, existsSync)) {\n\t\t\treturn candidate;\n\t\t}\n\t} catch {\n\t\t// Verified CLI resolution is optional; falling back to `pi` lets PATH handle execution.\n\t\treturn undefined;\n\t}\n\n\treturn undefined;\n}\n\nexport function getPiSpawnCommand(args: string[], deps: PiSpawnDeps = {}): PiSpawnCommand {\n\tconst env = deps.env ?? process.env;\n\tconst piBinary = env[PI_SUBAGENT_PI_BINARY_ENV]?.trim();\n\tif (piBinary) {\n\t\treturn { command: piBinary, args };\n\t}\n\n\tconst execPath = deps.execPath ?? process.execPath;\n\tif (isStandalonePiExecutable(execPath)) {\n\t\treturn { command: execPath, args };\n\t}\n\n\tconst piCliPath = resolvePiCliScript(deps);\n\tif (piCliPath) {\n\t\treturn {\n\t\t\tcommand: execPath,\n\t\t\targs: [piCliPath, ...args],\n\t\t};\n\t}\n\n\treturn { command: \"pi\", args };\n}\n"]}