mirror of
https://github.com/luckyyzh/pi-agent-integrated.git
synced 2026-10-03 02:59:35 +00:00
feat: integrate Pi backend and Pi Web
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env node
|
||||
"use strict";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const { getUnsupportedNodeVersionMessage, isNodeVersionSupported } = require("./node-version");
|
||||
|
||||
if (!isNodeVersionSupported(process.versions.node)) {
|
||||
console.error(getUnsupportedNodeVersionMessage(process.versions.node));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const { spawn } = require("child_process");
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const path = require("path");
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const fs = require("fs");
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const { parseLaunchOptions } = require("./pi-web-options");
|
||||
|
||||
const pkgDir = path.join(__dirname, "..");
|
||||
const nextDir = path.join(pkgDir, ".next");
|
||||
|
||||
// Resolve next's CLI entry directly to avoid relying on .bin symlinks (which
|
||||
// may not exist when installed via npx).
|
||||
let nextBin;
|
||||
try {
|
||||
nextBin = require.resolve("next/dist/bin/next", { paths: [pkgDir] });
|
||||
} catch {
|
||||
// Fallback: locate next package root and derive the bin path manually.
|
||||
try {
|
||||
const nextPkg = require.resolve("next/package.json", { paths: [pkgDir] });
|
||||
nextBin = path.join(path.dirname(nextPkg), "dist", "bin", "next");
|
||||
} catch {
|
||||
nextBin = path.join(pkgDir, "node_modules", "next", "dist", "bin", "next");
|
||||
}
|
||||
}
|
||||
|
||||
const { port, hostname, openBrowser } = parseLaunchOptions();
|
||||
const loopbackHostnames = new Set(["127.0.0.1", "localhost", "::1", "[::1]"]);
|
||||
|
||||
if (!fs.existsSync(nextDir)) {
|
||||
console.error("Build artifacts not found. Please report this issue.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!loopbackHostnames.has(hostname)) {
|
||||
console.warn(
|
||||
`Warning: pi-web is listening on ${hostname} without authentication. Only use this on a trusted network.`,
|
||||
);
|
||||
}
|
||||
|
||||
const nextArgs = ["start", "-p", port];
|
||||
nextArgs.push("-H", hostname);
|
||||
|
||||
// Always run next's JS entry with node directly — avoids .bin symlink issues
|
||||
// and path-with-spaces problems on Windows when shell: true is used.
|
||||
const child = spawn(process.execPath, [nextBin, ...nextArgs], {
|
||||
cwd: pkgDir,
|
||||
stdio: ["inherit", "pipe", "inherit"],
|
||||
env: { ...process.env, PI_WEB_HOSTNAME: hostname },
|
||||
});
|
||||
|
||||
let browserOpened = false;
|
||||
const url = `http://${hostname}:${port}`;
|
||||
|
||||
child.stdout.on("data", (chunk) => {
|
||||
const text = chunk.toString();
|
||||
process.stdout.write(text);
|
||||
if (openBrowser && !browserOpened && text.includes("Ready")) {
|
||||
browserOpened = true;
|
||||
const isWindows = process.platform === "win32";
|
||||
const isMac = process.platform === "darwin";
|
||||
const openCmd = isWindows ? "start" : isMac ? "open" : "xdg-open";
|
||||
const opener = spawn(openCmd, [url], {
|
||||
shell: isWindows,
|
||||
stdio: "ignore",
|
||||
detached: true,
|
||||
});
|
||||
|
||||
opener.on("error", (error) => {
|
||||
console.warn(`Could not open browser automatically: ${error.message}`);
|
||||
});
|
||||
|
||||
opener.unref();
|
||||
}
|
||||
});
|
||||
|
||||
child.on("exit", (code) => process.exit(code ?? 0));
|
||||
Reference in New Issue
Block a user