{"repo": "ashwin-pc/pi-web", "files": {"bin/pi-web.js": {"50cad3fc7787fc41a96e29a5322b7ecb050bdb24": {"t": 1785745519.1818075, "n": 4699, "h": "2006bb2589c351fa", "c": "#!/usr/bin/env node\nimport { spawn } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { constants as osConstants, homedir } from \"node:os\";\nimport { createInterface } from \"node:readline/promises\";\nimport { join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst appDir = fileURLToPath(new URL(\"..\", import.meta.url));\nconst env = { ...process.env };\n\nconst providerEnvVars = [\n \"ANTHROPIC_API_KEY\",\n \"ANTHROPIC_OAUTH_TOKEN\",\n \"OPENAI_API_KEY\",\n \"GEMINI_API_KEY\",\n \"GOOGLE_API_KEY\",\n \"DEEPSEEK_API_KEY\",\n \"NVIDIA_API_KEY\",\n \"GROQ_API_KEY\",\n \"CEREBRAS_API_KEY\",\n \"XAI_API_KEY\",\n \"OPENROUTER_API_KEY\",\n \"AI_GATEWAY_API_KEY\",\n \"ZAI_API_KEY\",\n \"ZAI_CODING_CN_API_KEY\",\n \"MISTRAL_API_KEY\",\n \"MINIMAX_API_KEY\",\n \"MINIMAX_CN_API_KEY\",\n \"MOONSHOT_API_KEY\",\n \"OPENCODE_API_KEY\",\n \"KIMI_API_KEY\",\n \"CLOUDFLARE_API_KEY\",\n \"TOGETHER_API_KEY\",\n \"FIREWORKS_API_KEY\",\n \"HF_TOKEN\",\n \"XIAOMI_API_KEY\",\n \"XIAOMI_TOKEN_PLAN_CN_API_KEY\",\n \"XIAOMI_TOKEN_PLAN_AMS_API_KEY\",\n \"XIAOMI_TOKEN_PLAN_SGP_API_KEY\",\n \"AWS_PROFILE\",\n \"AWS_ACCESS_KEY_ID\",\n \"AWS_BEARER_TOKEN_BEDROCK\",\n];\n\nfunction hasProviderEnv() {\n return providerEnvVars.some((name) => Boolean(env[name]?.trim()));\n}\n\nfunction agentDir() {\n return env.PI_CODING_AGENT_DIR || join(homedir(), \".pi\", \"agent\");\n}\n\nfunction hasAuthFile() {\n const authPath = join(agentDir(), \"auth.json\");\n if (!existsSync(authPath)) return false;\n try {\n const auth = JSON.parse(readFileSync(authPath, \"utf8\"));\n return Boolean(auth && typeof auth === \"object\" && Object.keys(auth).length > 0);\n } catch {\n return false;\n }\n}\n\nfunction hasCustomModelsFile() {\n const modelsPath = join(agentDir(), \"models.json\");\n if (!existsSync(modelsPath)) return false;\n try {\n const models = JSON.parse(readFileSync(modelsPath, \"utf8\"));\n return Boolean(models?.providers && typeof models.providers === \"object\" && Object.keys(models.providers).length > 0);\n } catch {\n return false;\n }\n}\n\nfunction hasProviderConfiguration() {\n return hasProviderEnv() || hasAuthFile() || hasCustomModelsFile();\n}\n\nfunction waitForExit(child) {\n return new Promise((resolve, reject) => {\n child.on(\"exit\", (code, signal) => resolve({ code, signal }));\n child.on(\"error\", reject);\n });\n}\n\nfunction findPiCli() {\n const candidates = [\n join(appDir, \"node_modules\", \"@earendil-works\", \"pi-coding-agent\", \"dist\", \"cli.js\"),\n join(appDir, \"..\", \"..\", \"@earendil-works\", \"pi-coding-agent\", \"dist\", \"cli.js\"),\n ];\n return candidates.find((candidate) => existsSync(candidate));\n}\n\nasync function maybeRunPiLogin() {\n if (env.PI_WEB_SKIP_PROVIDER_ONBOARDING === \"1\" || env.CI === \"1\" || hasProviderConfiguration()) return;\n\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n console.warn(\"pi-web: no Pi provider credentials found. Run `pi` and use `/login`, or set an API key env var, to connect an LLM provider.\");\n return;\n }\n\n console.log(\"\\nNo Pi LLM provider configuration was found.\");\n console.log(\"pi-web uses the same provider login as the Pi CLI.\");\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n const answer = (await rl.question(\"Open Pi now so you can run /login? [Y/n] \")).trim().toLowerCase();\n rl.close();\n if (answer === \"n\" || answer === \"no\") return;\n\n console.log(\"\\nStarting Pi. Run /login, complete provider setup, then exit Pi to continue starting pi-web.\\n\");\n const piCli = findPiCli();\n if (!piCli) {\n console.warn(\"pi-web: could not find the bundled Pi CLI. Run `pi` and use `/login`, then start pi-web again.\");\n return;\n }\n const result = await waitForExit(spawn(process.execPath, [piCli], { cwd: env.PI_WEB_CWD || process.cwd(), env, stdio: \"inherit\" }));\n if (result.code && result.code !== 0) console.warn(`pi-web: Pi exited with code ${result.code}; starting pi-web anyway.`);\n}\n\nenv.PI_WEB_CWD ||= process.cwd();\nenv.PI_WEB_DEV = \"0\";\nenv.NODE_ENV = \"production\";\n\nawait maybeRunPiLogin();\n\nconst child = spawn(process.execPath, [\"--import\", \"tsx\", \"supervisor.ts\"], {\n cwd: appDir,\n env,\n stdio: \"inherit\",\n});\n\nconst forwardedSignals = [\"SIGINT\", \"SIGTERM\", \"SIGHUP\"];\nfor (const signal of forwardedSignals) {\n process.on(signal, () => {\n if (!child.killed) child.kill(signal);\n });\n}\n\nchild.on(\"exit\", (code, signal) => {\n for (const forwardedSignal of forwardedSignals) process.removeAllListeners(forwardedSignal);\n const signalNumber = signal ? osConstants.signals[signal] : undefined;\n process.exit(code ?? (signalNumber ? 128 + signalNumber : 0));\n});\n\nchild.on(\"error\", (error) => {\n console.error(`pi-web failed to start: ${error.message}`);\n process.exit(1);\n});\n"}, "d2209b12400024b53ec153ce014685664aefa1fc": {"t": 1785753810.2710488, "n": 4699, "h": "2006bb2589c351fa", "c": "#!/usr/bin/env node\nimport { spawn } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { constants as osConstants, homedir } from \"node:os\";\nimport { createInterface } from \"node:readline/promises\";\nimport { join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst appDir = fileURLToPath(new URL(\"..\", import.meta.url));\nconst env = { ...process.env };\n\nconst providerEnvVars = [\n \"ANTHROPIC_API_KEY\",\n \"ANTHROPIC_OAUTH_TOKEN\",\n \"OPENAI_API_KEY\",\n \"GEMINI_API_KEY\",\n \"GOOGLE_API_KEY\",\n \"DEEPSEEK_API_KEY\",\n \"NVIDIA_API_KEY\",\n \"GROQ_API_KEY\",\n \"CEREBRAS_API_KEY\",\n \"XAI_API_KEY\",\n \"OPENROUTER_API_KEY\",\n \"AI_GATEWAY_API_KEY\",\n \"ZAI_API_KEY\",\n \"ZAI_CODING_CN_API_KEY\",\n \"MISTRAL_API_KEY\",\n \"MINIMAX_API_KEY\",\n \"MINIMAX_CN_API_KEY\",\n \"MOONSHOT_API_KEY\",\n \"OPENCODE_API_KEY\",\n \"KIMI_API_KEY\",\n \"CLOUDFLARE_API_KEY\",\n \"TOGETHER_API_KEY\",\n \"FIREWORKS_API_KEY\",\n \"HF_TOKEN\",\n \"XIAOMI_API_KEY\",\n \"XIAOMI_TOKEN_PLAN_CN_API_KEY\",\n \"XIAOMI_TOKEN_PLAN_AMS_API_KEY\",\n \"XIAOMI_TOKEN_PLAN_SGP_API_KEY\",\n \"AWS_PROFILE\",\n \"AWS_ACCESS_KEY_ID\",\n \"AWS_BEARER_TOKEN_BEDROCK\",\n];\n\nfunction hasProviderEnv() {\n return providerEnvVars.some((name) => Boolean(env[name]?.trim()));\n}\n\nfunction agentDir() {\n return env.PI_CODING_AGENT_DIR || join(homedir(), \".pi\", \"agent\");\n}\n\nfunction hasAuthFile() {\n const authPath = join(agentDir(), \"auth.json\");\n if (!existsSync(authPath)) return false;\n try {\n const auth = JSON.parse(readFileSync(authPath, \"utf8\"));\n return Boolean(auth && typeof auth === \"object\" && Object.keys(auth).length > 0);\n } catch {\n return false;\n }\n}\n\nfunction hasCustomModelsFile() {\n const modelsPath = join(agentDir(), \"models.json\");\n if (!existsSync(modelsPath)) return false;\n try {\n const models = JSON.parse(readFileSync(modelsPath, \"utf8\"));\n return Boolean(models?.providers && typeof models.providers === \"object\" && Object.keys(models.providers).length > 0);\n } catch {\n return false;\n }\n}\n\nfunction hasProviderConfiguration() {\n return hasProviderEnv() || hasAuthFile() || hasCustomModelsFile();\n}\n\nfunction waitForExit(child) {\n return new Promise((resolve, reject) => {\n child.on(\"exit\", (code, signal) => resolve({ code, signal }));\n child.on(\"error\", reject);\n });\n}\n\nfunction findPiCli() {\n const candidates = [\n join(appDir, \"node_modules\", \"@earendil-works\", \"pi-coding-agent\", \"dist\", \"cli.js\"),\n join(appDir, \"..\", \"..\", \"@earendil-works\", \"pi-coding-agent\", \"dist\", \"cli.js\"),\n ];\n return candidates.find((candidate) => existsSync(candidate));\n}\n\nasync function maybeRunPiLogin() {\n if (env.PI_WEB_SKIP_PROVIDER_ONBOARDING === \"1\" || env.CI === \"1\" || hasProviderConfiguration()) return;\n\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n console.warn(\"pi-web: no Pi provider credentials found. Run `pi` and use `/login`, or set an API key env var, to connect an LLM provider.\");\n return;\n }\n\n console.log(\"\\nNo Pi LLM provider configuration was found.\");\n console.log(\"pi-web uses the same provider login as the Pi CLI.\");\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n const answer = (await rl.question(\"Open Pi now so you can run /login? [Y/n] \")).trim().toLowerCase();\n rl.close();\n if (answer === \"n\" || answer === \"no\") return;\n\n console.log(\"\\nStarting Pi. Run /login, complete provider setup, then exit Pi to continue starting pi-web.\\n\");\n const piCli = findPiCli();\n if (!piCli) {\n console.warn(\"pi-web: could not find the bundled Pi CLI. Run `pi` and use `/login`, then start pi-web again.\");\n return;\n }\n const result = await waitForExit(spawn(process.execPath, [piCli], { cwd: env.PI_WEB_CWD || process.cwd(), env, stdio: \"inherit\" }));\n if (result.code && result.code !== 0) console.warn(`pi-web: Pi exited with code ${result.code}; starting pi-web anyway.`);\n}\n\nenv.PI_WEB_CWD ||= process.cwd();\nenv.PI_WEB_DEV = \"0\";\nenv.NODE_ENV = \"production\";\n\nawait maybeRunPiLogin();\n\nconst child = spawn(process.execPath, [\"--import\", \"tsx\", \"supervisor.ts\"], {\n cwd: appDir,\n env,\n stdio: \"inherit\",\n});\n\nconst forwardedSignals = [\"SIGINT\", \"SIGTERM\", \"SIGHUP\"];\nfor (const signal of forwardedSignals) {\n process.on(signal, () => {\n if (!child.killed) child.kill(signal);\n });\n}\n\nchild.on(\"exit\", (code, signal) => {\n for (const forwardedSignal of forwardedSignals) process.removeAllListeners(forwardedSignal);\n const signalNumber = signal ? osConstants.signals[signal] : undefined;\n process.exit(code ?? (signalNumber ? 128 + signalNumber : 0));\n});\n\nchild.on(\"error\", (error) => {\n console.error(`pi-web failed to start: ${error.message}`);\n process.exit(1);\n});\n"}, "0bcc5b78e292882442222d4b6413b9c654a6a8be": {"t": 1785753811.4535975, "n": 4693, "h": "3b3f955a90c8533a", "c": "#!/usr/bin/env node\nimport { spawn } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { constants as osConstants, homedir } from \"node:os\";\nimport { createInterface } from \"node:readline/promises\";\nimport { join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst appDir = fileURLToPath(new URL(\"..\", import.meta.url));\nconst env = { ...process.env };\n\nconst providerEnvVars = [\n \"ANTHROPIC_API_KEY\",\n \"ANTHROPIC_OAUTH_TOKEN\",\n \"OPENAI_API_KEY\",\n \"GEMINI_API_KEY\",\n \"GOOGLE_API_KEY\",\n \"DEEPSEEK_API_KEY\",\n \"NVIDIA_API_KEY\",\n \"GROQ_API_KEY\",\n \"CEREBRAS_API_KEY\",\n \"XAI_API_KEY\",\n \"OPENROUTER_API_KEY\",\n \"AI_GATEWAY_API_KEY\",\n \"ZAI_API_KEY\",\n \"ZAI_CODING_CN_API_KEY\",\n \"MISTRAL_API_KEY\",\n \"MINIMAX_API_KEY\",\n \"MINIMAX_CN_API_KEY\",\n \"MOONSHOT_API_KEY\",\n \"OPENCODE_API_KEY\",\n \"KIMI_API_KEY\",\n \"CLOUDFLARE_API_KEY\",\n \"TOGETHER_API_KEY\",\n \"FIREWORKS_API_KEY\",\n \"HF_TOKEN\",\n \"XIAOMI_API_KEY\",\n \"XIAOMI_TOKEN_PLAN_CN_API_KEY\",\n \"XIAOMI_TOKEN_PLAN_AMS_API_KEY\",\n \"XIAOMI_TOKEN_PLAN_SGP_API_KEY\",\n \"AWS_PROFILE\",\n \"AWS_ACCESS_KEY_ID\",\n \"AWS_BEARER_TOKEN_BEDROCK\",\n];\n\nfunction hasProviderEnv() {\n return providerEnvVars.some((name) => Boolean(env[name]?.trim()));\n}\n\nfunction agentDir() {\n return env.PI_CODING_AGENT_DIR || join(homedir(), \".pi\", \"agent\");\n}\n\nfunction hasAuthFile() {\n const authPath = join(agentDir(), \"auth.json\");\n if (!existsSync(authPath)) return false;\n try {\n const auth = JSON.parse(readFileSync(authPath, \"utf8\"));\n return Boolean(auth && typeof auth === \"object\" && Object.keys(auth).length > 0);\n } catch {\n return false;\n }\n}\n\nfunction hasCustomModelsFile() {\n const modelsPath = join(agentDir(), \"models.json\");\n if (!existsSync(modelsPath)) return false;\n try {\n const models = JSON.parse(readFileSync(modelsPath, \"utf8\"));\n return Boolean(models?.providers && typeof models.providers === \"object\" && Object.keys(models.providers).length > 0);\n } catch {\n return false;\n }\n}\n\nfunction hasProviderConfiguration() {\n return hasProviderEnv() || hasAuthFile() || hasCustomModelsFile();\n}\n\nfunction waitForExit(child) {\n return new Promise((resolve, reject) => {\n child.on(\"exit\", (code, signal) => resolve({ code, signal }));\n child.on(\"error\", reject);\n });\n}\n\nfunction findPiCli() {\n const candidates = [\n join(appDir, \"node_modules\", \"@earendil-works\", \"pi-coding-agent\", \"dist\", \"cli.js\"),\n join(appDir, \"..\", \"@earendil-works\", \"pi-coding-agent\", \"dist\", \"cli.js\"),\n ];\n return candidates.find((candidate) => existsSync(candidate));\n}\n\nasync function maybeRunPiLogin() {\n if (env.PI_WEB_SKIP_PROVIDER_ONBOARDING === \"1\" || env.CI === \"1\" || hasProviderConfiguration()) return;\n\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n console.warn(\"pi-web: no Pi provider credentials found. Run `pi` and use `/login`, or set an API key env var, to connect an LLM provider.\");\n return;\n }\n\n console.log(\"\\nNo Pi LLM provider configuration was found.\");\n console.log(\"pi-web uses the same provider login as the Pi CLI.\");\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n const answer = (await rl.question(\"Open Pi now so you can run /login? [Y/n] \")).trim().toLowerCase();\n rl.close();\n if (answer === \"n\" || answer === \"no\") return;\n\n console.log(\"\\nStarting Pi. Run /login, complete provider setup, then exit Pi to continue starting pi-web.\\n\");\n const piCli = findPiCli();\n if (!piCli) {\n console.warn(\"pi-web: could not find the bundled Pi CLI. Run `pi` and use `/login`, then start pi-web again.\");\n return;\n }\n const result = await waitForExit(spawn(process.execPath, [piCli], { cwd: env.PI_WEB_CWD || process.cwd(), env, stdio: \"inherit\" }));\n if (result.code && result.code !== 0) console.warn(`pi-web: Pi exited with code ${result.code}; starting pi-web anyway.`);\n}\n\nenv.PI_WEB_CWD ||= process.cwd();\nenv.PI_WEB_DEV = \"0\";\nenv.NODE_ENV = \"production\";\n\nawait maybeRunPiLogin();\n\nconst child = spawn(process.execPath, [\"--import\", \"tsx\", \"supervisor.ts\"], {\n cwd: appDir,\n env,\n stdio: \"inherit\",\n});\n\nconst forwardedSignals = [\"SIGINT\", \"SIGTERM\", \"SIGHUP\"];\nfor (const signal of forwardedSignals) {\n process.on(signal, () => {\n if (!child.killed) child.kill(signal);\n });\n}\n\nchild.on(\"exit\", (code, signal) => {\n for (const forwardedSignal of forwardedSignals) process.removeAllListeners(forwardedSignal);\n const signalNumber = signal ? osConstants.signals[signal] : undefined;\n process.exit(code ?? (signalNumber ? 128 + signalNumber : 0));\n});\n\nchild.on(\"error\", (error) => {\n console.error(`pi-web failed to start: ${error.message}`);\n process.exit(1);\n});\n"}, "22027bd4ac94d8d870273d1ea118a93fbc4a081b": {"t": 1785753813.1101263, "n": 4448, "h": "759556399a480309", "c": "#!/usr/bin/env node\nimport { spawn } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { constants as osConstants, homedir } from \"node:os\";\nimport { createInterface } from \"node:readline/promises\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst appDir = fileURLToPath(new URL(\"..\", import.meta.url));\nconst require = createRequire(import.meta.url);\nconst env = { ...process.env };\n\nconst providerEnvVars = [\n \"ANTHROPIC_API_KEY\",\n \"ANTHROPIC_OAUTH_TOKEN\",\n \"OPENAI_API_KEY\",\n \"GEMINI_API_KEY\",\n \"GOOGLE_API_KEY\",\n \"DEEPSEEK_API_KEY\",\n \"NVIDIA_API_KEY\",\n \"GROQ_API_KEY\",\n \"CEREBRAS_API_KEY\",\n \"XAI_API_KEY\",\n \"OPENROUTER_API_KEY\",\n \"AI_GATEWAY_API_KEY\",\n \"ZAI_API_KEY\",\n \"ZAI_CODING_CN_API_KEY\",\n \"MISTRAL_API_KEY\",\n \"MINIMAX_API_KEY\",\n \"MINIMAX_CN_API_KEY\",\n \"MOONSHOT_API_KEY\",\n \"OPENCODE_API_KEY\",\n \"KIMI_API_KEY\",\n \"CLOUDFLARE_API_KEY\",\n \"TOGETHER_API_KEY\",\n \"FIREWORKS_API_KEY\",\n \"HF_TOKEN\",\n \"XIAOMI_API_KEY\",\n \"XIAOMI_TOKEN_PLAN_CN_API_KEY\",\n \"XIAOMI_TOKEN_PLAN_AMS_API_KEY\",\n \"XIAOMI_TOKEN_PLAN_SGP_API_KEY\",\n \"AWS_PROFILE\",\n \"AWS_ACCESS_KEY_ID\",\n \"AWS_BEARER_TOKEN_BEDROCK\",\n];\n\nfunction hasProviderEnv() {\n return providerEnvVars.some((name) => Boolean(env[name]?.trim()));\n}\n\nfunction agentDir() {\n return env.PI_CODING_AGENT_DIR || join(homedir(), \".pi\", \"agent\");\n}\n\nfunction hasAuthFile() {\n const authPath = join(agentDir(), \"auth.json\");\n if (!existsSync(authPath)) return false;\n try {\n const auth = JSON.parse(readFileSync(authPath, \"utf8\"));\n return Boolean(auth && typeof auth === \"object\" && Object.keys(auth).length > 0);\n } catch {\n return false;\n }\n}\n\nfunction hasCustomModelsFile() {\n const modelsPath = join(agentDir(), \"models.json\");\n if (!existsSync(modelsPath)) return false;\n try {\n const models = JSON.parse(readFileSync(modelsPath, \"utf8\"));\n return Boolean(models?.providers && typeof models.providers === \"object\" && Object.keys(models.providers).length > 0);\n } catch {\n return false;\n }\n}\n\nfunction hasProviderConfiguration() {\n return hasProviderEnv() || hasAuthFile() || hasCustomModelsFile();\n}\n\nfunction waitForExit(child) {\n return new Promise((resolve, reject) => {\n child.on(\"exit\", (code, signal) => resolve({ code, signal }));\n child.on(\"error\", reject);\n });\n}\n\nasync function maybeRunPiLogin() {\n if (env.PI_WEB_SKIP_PROVIDER_ONBOARDING === \"1\" || env.CI === \"1\" || hasProviderConfiguration()) return;\n\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n console.warn(\"pi-web: no Pi provider credentials found. Run `pi` and use `/login`, or set an API key env var, to connect an LLM provider.\");\n return;\n }\n\n console.log(\"\\nNo Pi LLM provider configuration was found.\");\n console.log(\"pi-web uses the same provider login as the Pi CLI.\");\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n const answer = (await rl.question(\"Open Pi now so you can run /login? [Y/n] \")).trim().toLowerCase();\n rl.close();\n if (answer === \"n\" || answer === \"no\") return;\n\n console.log(\"\\nStarting Pi. Run /login, complete provider setup, then exit Pi to continue starting pi-web.\\n\");\n const piMain = require.resolve(\"@earendil-works/pi-coding-agent\");\n const piCli = join(dirname(piMain), \"cli.js\");\n const result = await waitForExit(spawn(process.execPath, [piCli], { cwd: env.PI_WEB_CWD || process.cwd(), env, stdio: \"inherit\" }));\n if (result.code && result.code !== 0) console.warn(`pi-web: Pi exited with code ${result.code}; starting pi-web anyway.`);\n}\n\nenv.PI_WEB_CWD ||= process.cwd();\nenv.PI_WEB_DEV = \"0\";\nenv.NODE_ENV = \"production\";\n\nawait maybeRunPiLogin();\n\nconst child = spawn(process.execPath, [\"--import\", \"tsx\", \"supervisor.ts\"], {\n cwd: appDir,\n env,\n stdio: \"inherit\",\n});\n\nconst forwardedSignals = [\"SIGINT\", \"SIGTERM\", \"SIGHUP\"];\nfor (const signal of forwardedSignals) {\n process.on(signal, () => {\n if (!child.killed) child.kill(signal);\n });\n}\n\nchild.on(\"exit\", (code, signal) => {\n for (const forwardedSignal of forwardedSignals) process.removeAllListeners(forwardedSignal);\n const signalNumber = signal ? osConstants.signals[signal] : undefined;\n process.exit(code ?? (signalNumber ? 128 + signalNumber : 0));\n});\n\nchild.on(\"error\", (error) => {\n console.error(`pi-web failed to start: ${error.message}`);\n process.exit(1);\n});\n"}, "0f13f2d5549bee8835652a7260ab7720087e0399": {"t": 1785753814.8736563, "n": 4348, "h": "d65e8d02189e96a8", "c": "#!/usr/bin/env node\nimport { spawn } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { constants as osConstants, homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { createInterface } from \"node:readline/promises\";\nimport { fileURLToPath } from \"node:url\";\n\nconst appDir = fileURLToPath(new URL(\"..\", import.meta.url));\nconst env = { ...process.env };\n\nconst providerEnvVars = [\n \"ANTHROPIC_API_KEY\",\n \"ANTHROPIC_OAUTH_TOKEN\",\n \"OPENAI_API_KEY\",\n \"GEMINI_API_KEY\",\n \"GOOGLE_API_KEY\",\n \"DEEPSEEK_API_KEY\",\n \"NVIDIA_API_KEY\",\n \"GROQ_API_KEY\",\n \"CEREBRAS_API_KEY\",\n \"XAI_API_KEY\",\n \"OPENROUTER_API_KEY\",\n \"AI_GATEWAY_API_KEY\",\n \"ZAI_API_KEY\",\n \"ZAI_CODING_CN_API_KEY\",\n \"MISTRAL_API_KEY\",\n \"MINIMAX_API_KEY\",\n \"MINIMAX_CN_API_KEY\",\n \"MOONSHOT_API_KEY\",\n \"OPENCODE_API_KEY\",\n \"KIMI_API_KEY\",\n \"CLOUDFLARE_API_KEY\",\n \"TOGETHER_API_KEY\",\n \"FIREWORKS_API_KEY\",\n \"HF_TOKEN\",\n \"XIAOMI_API_KEY\",\n \"XIAOMI_TOKEN_PLAN_CN_API_KEY\",\n \"XIAOMI_TOKEN_PLAN_AMS_API_KEY\",\n \"XIAOMI_TOKEN_PLAN_SGP_API_KEY\",\n \"AWS_PROFILE\",\n \"AWS_ACCESS_KEY_ID\",\n \"AWS_BEARER_TOKEN_BEDROCK\",\n];\n\nfunction hasProviderEnv() {\n return providerEnvVars.some((name) => Boolean(env[name]?.trim()));\n}\n\nfunction agentDir() {\n return env.PI_CODING_AGENT_DIR || join(homedir(), \".pi\", \"agent\");\n}\n\nfunction hasAuthFile() {\n const authPath = join(agentDir(), \"auth.json\");\n if (!existsSync(authPath)) return false;\n try {\n const auth = JSON.parse(readFileSync(authPath, \"utf8\"));\n return Boolean(auth && typeof auth === \"object\" && Object.keys(auth).length > 0);\n } catch {\n return false;\n }\n}\n\nfunction hasCustomModelsFile() {\n const modelsPath = join(agentDir(), \"models.json\");\n if (!existsSync(modelsPath)) return false;\n try {\n const models = JSON.parse(readFileSync(modelsPath, \"utf8\"));\n return Boolean(models?.providers && typeof models.providers === \"object\" && Object.keys(models.providers).length > 0);\n } catch {\n return false;\n }\n}\n\nfunction hasProviderConfiguration() {\n return hasProviderEnv() || hasAuthFile() || hasCustomModelsFile();\n}\n\nfunction waitForExit(child) {\n return new Promise((resolve, reject) => {\n child.on(\"exit\", (code, signal) => resolve({ code, signal }));\n child.on(\"error\", reject);\n });\n}\n\nasync function maybeRunPiLogin() {\n if (env.PI_WEB_SKIP_PROVIDER_ONBOARDING === \"1\" || env.CI === \"1\" || hasProviderConfiguration()) return;\n\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n console.warn(\"pi-web: no Pi provider credentials found. Run `pi` and use `/login`, or set an API key env var, to connect an LLM provider.\");\n return;\n }\n\n console.log(\"\\nNo Pi LLM provider configuration was found.\");\n console.log(\"pi-web uses the same provider login as the Pi CLI.\");\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n const answer = (await rl.question(\"Open Pi now so you can run /login? [Y/n] \")).trim().toLowerCase();\n rl.close();\n if (answer === \"n\" || answer === \"no\") return;\n\n console.log(\"\\nStarting Pi. Run /login, complete provider setup, then exit Pi to continue starting pi-web.\\n\");\n const piCli = fileURLToPath(new URL(\"../node_modules/@earendil-works/pi-coding-agent/dist/cli.js\", import.meta.url));\n const result = await waitForExit(spawn(process.execPath, [piCli], { cwd: env.PI_WEB_CWD || process.cwd(), env, stdio: \"inherit\" }));\n if (result.code && result.code !== 0) console.warn(`pi-web: Pi exited with code ${result.code}; starting pi-web anyway.`);\n}\n\nenv.PI_WEB_CWD ||= process.cwd();\nenv.PI_WEB_DEV = \"0\";\nenv.NODE_ENV = \"production\";\n\nawait maybeRunPiLogin();\n\nconst child = spawn(process.execPath, [\"--import\", \"tsx\", \"supervisor.ts\"], {\n cwd: appDir,\n env,\n stdio: \"inherit\",\n});\n\nconst forwardedSignals = [\"SIGINT\", \"SIGTERM\", \"SIGHUP\"];\nfor (const signal of forwardedSignals) {\n process.on(signal, () => {\n if (!child.killed) child.kill(signal);\n });\n}\n\nchild.on(\"exit\", (code, signal) => {\n for (const forwardedSignal of forwardedSignals) process.removeAllListeners(forwardedSignal);\n const signalNumber = signal ? osConstants.signals[signal] : undefined;\n process.exit(code ?? (signalNumber ? 128 + signalNumber : 0));\n});\n\nchild.on(\"error\", (error) => {\n console.error(`pi-web failed to start: ${error.message}`);\n process.exit(1);\n});\n"}, "4e6f1c7084a73b2394d2520b822046ebb6509077": {"t": 1785753816.2922983, "n": 1035, "h": "c16f1f050bb94df8", "c": "#!/usr/bin/env node\nimport { spawn } from \"node:child_process\";\nimport { constants as osConstants } from \"node:os\";\nimport { fileURLToPath } from \"node:url\";\n\nconst appDir = fileURLToPath(new URL(\"..\", import.meta.url));\nconst env = { ...process.env };\n\nenv.PI_WEB_CWD ||= process.cwd();\nenv.PI_WEB_DEV = \"0\";\nenv.NODE_ENV = \"production\";\n\nconst child = spawn(process.execPath, [\"--import\", \"tsx\", \"supervisor.ts\"], {\n cwd: appDir,\n env,\n stdio: \"inherit\",\n});\n\nconst forwardedSignals = [\"SIGINT\", \"SIGTERM\", \"SIGHUP\"];\nfor (const signal of forwardedSignals) {\n process.on(signal, () => {\n if (!child.killed) child.kill(signal);\n });\n}\n\nchild.on(\"exit\", (code, signal) => {\n for (const forwardedSignal of forwardedSignals) process.removeAllListeners(forwardedSignal);\n const signalNumber = signal ? osConstants.signals[signal] : undefined;\n process.exit(code ?? (signalNumber ? 128 + signalNumber : 0));\n});\n\nchild.on(\"error\", (error) => {\n console.error(`pi-web failed to start: ${error.message}`);\n process.exit(1);\n});\n"}}}}