Fix runtime package resolution and tty shutdown
This commit is contained in:
@@ -51,6 +51,7 @@ const cliPath = piPackageRoot ? resolve(piPackageRoot, "dist", "cli.js") : null;
|
|||||||
const bunCliPath = piPackageRoot ? resolve(piPackageRoot, "dist", "bun", "cli.js") : null;
|
const bunCliPath = piPackageRoot ? resolve(piPackageRoot, "dist", "bun", "cli.js") : null;
|
||||||
const interactiveModePath = piPackageRoot ? resolve(piPackageRoot, "dist", "modes", "interactive", "interactive-mode.js") : null;
|
const interactiveModePath = piPackageRoot ? resolve(piPackageRoot, "dist", "modes", "interactive", "interactive-mode.js") : null;
|
||||||
const interactiveThemePath = piPackageRoot ? resolve(piPackageRoot, "dist", "modes", "interactive", "theme", "theme.js") : null;
|
const interactiveThemePath = piPackageRoot ? resolve(piPackageRoot, "dist", "modes", "interactive", "theme", "theme.js") : null;
|
||||||
|
const terminalPath = piTuiRoot ? resolve(piTuiRoot, "dist", "terminal.js") : null;
|
||||||
const editorPath = piTuiRoot ? resolve(piTuiRoot, "dist", "components", "editor.js") : null;
|
const editorPath = piTuiRoot ? resolve(piTuiRoot, "dist", "components", "editor.js") : null;
|
||||||
const workspaceRoot = resolve(appRoot, ".feynman", "npm", "node_modules");
|
const workspaceRoot = resolve(appRoot, ".feynman", "npm", "node_modules");
|
||||||
const webAccessPath = resolve(workspaceRoot, "pi-web-access", "index.ts");
|
const webAccessPath = resolve(workspaceRoot, "pi-web-access", "index.ts");
|
||||||
@@ -247,10 +248,68 @@ for (const entryPath of [cliPath, bunCliPath].filter(Boolean)) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cliSource = readFileSync(entryPath, "utf8");
|
let cliSource = readFileSync(entryPath, "utf8");
|
||||||
if (cliSource.includes('process.title = "pi";')) {
|
if (cliSource.includes('process.title = "pi";')) {
|
||||||
writeFileSync(entryPath, cliSource.replace('process.title = "pi";', 'process.title = "feynman";'), "utf8");
|
cliSource = cliSource.replace('process.title = "pi";', 'process.title = "feynman";');
|
||||||
}
|
}
|
||||||
|
const stdinErrorGuard = [
|
||||||
|
"const feynmanHandleStdinError = (error) => {",
|
||||||
|
' if (error && typeof error === "object") {',
|
||||||
|
' const code = "code" in error ? error.code : undefined;',
|
||||||
|
' const syscall = "syscall" in error ? error.syscall : undefined;',
|
||||||
|
' if ((code === "EIO" || code === "EBADF") && syscall === "read") {',
|
||||||
|
" return;",
|
||||||
|
" }",
|
||||||
|
" }",
|
||||||
|
"};",
|
||||||
|
'process.stdin?.on?.("error", feynmanHandleStdinError);',
|
||||||
|
].join("\n");
|
||||||
|
if (!cliSource.includes('process.stdin?.on?.("error", feynmanHandleStdinError);')) {
|
||||||
|
cliSource = cliSource.replace(
|
||||||
|
'process.emitWarning = (() => { });',
|
||||||
|
`process.emitWarning = (() => { });\n${stdinErrorGuard}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
writeFileSync(entryPath, cliSource, "utf8");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (terminalPath && existsSync(terminalPath)) {
|
||||||
|
let terminalSource = readFileSync(terminalPath, "utf8");
|
||||||
|
if (!terminalSource.includes("stdinErrorHandler;")) {
|
||||||
|
terminalSource = terminalSource.replace(
|
||||||
|
" stdinBuffer;\n stdinDataHandler;\n",
|
||||||
|
[
|
||||||
|
" stdinBuffer;",
|
||||||
|
" stdinDataHandler;",
|
||||||
|
" stdinErrorHandler = (error) => {",
|
||||||
|
' if ((error?.code === "EIO" || error?.code === "EBADF") && error?.syscall === "read") {',
|
||||||
|
" return;",
|
||||||
|
" }",
|
||||||
|
" };",
|
||||||
|
].join("\n") + "\n",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!terminalSource.includes('process.stdin.on("error", this.stdinErrorHandler);')) {
|
||||||
|
terminalSource = terminalSource.replace(
|
||||||
|
' process.stdin.resume();\n',
|
||||||
|
' process.stdin.resume();\n process.stdin.on("error", this.stdinErrorHandler);\n',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!terminalSource.includes(' process.stdin.removeListener("error", this.stdinErrorHandler);')) {
|
||||||
|
terminalSource = terminalSource.replace(
|
||||||
|
' process.stdin.removeListener("data", onData);\n this.inputHandler = previousHandler;\n',
|
||||||
|
[
|
||||||
|
' process.stdin.removeListener("data", onData);',
|
||||||
|
' process.stdin.removeListener("error", this.stdinErrorHandler);',
|
||||||
|
' this.inputHandler = previousHandler;',
|
||||||
|
].join("\n"),
|
||||||
|
);
|
||||||
|
terminalSource = terminalSource.replace(
|
||||||
|
' process.stdin.pause();\n',
|
||||||
|
' process.stdin.removeListener("error", this.stdinErrorHandler);\n process.stdin.pause();\n',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
writeFileSync(terminalPath, terminalSource, "utf8");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (interactiveModePath && existsSync(interactiveModePath)) {
|
if (interactiveModePath && existsSync(interactiveModePath)) {
|
||||||
|
|||||||
@@ -77,9 +77,12 @@ export function buildPiArgs(options: PiRuntimeOptions): string[] {
|
|||||||
|
|
||||||
export function buildPiEnv(options: PiRuntimeOptions): NodeJS.ProcessEnv {
|
export function buildPiEnv(options: PiRuntimeOptions): NodeJS.ProcessEnv {
|
||||||
const paths = resolvePiPaths(options.appRoot);
|
const paths = resolvePiPaths(options.appRoot);
|
||||||
|
const feynmanHome = dirname(options.feynmanAgentDir);
|
||||||
|
const feynmanNpmPrefixPath = resolve(feynmanHome, "npm-global");
|
||||||
|
const feynmanNpmBinPath = resolve(feynmanNpmPrefixPath, "bin");
|
||||||
|
|
||||||
const currentPath = process.env.PATH ?? "";
|
const currentPath = process.env.PATH ?? "";
|
||||||
const binEntries = [paths.nodeModulesBinPath, resolve(paths.piWorkspaceNodeModulesPath, ".bin")];
|
const binEntries = [paths.nodeModulesBinPath, resolve(paths.piWorkspaceNodeModulesPath, ".bin"), feynmanNpmBinPath];
|
||||||
const binPath = binEntries.join(":");
|
const binPath = binEntries.join(":");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -90,11 +93,14 @@ export function buildPiEnv(options: PiRuntimeOptions): NodeJS.ProcessEnv {
|
|||||||
FEYNMAN_MEMORY_DIR: resolve(dirname(options.feynmanAgentDir), "memory"),
|
FEYNMAN_MEMORY_DIR: resolve(dirname(options.feynmanAgentDir), "memory"),
|
||||||
FEYNMAN_NODE_EXECUTABLE: process.execPath,
|
FEYNMAN_NODE_EXECUTABLE: process.execPath,
|
||||||
FEYNMAN_BIN_PATH: resolve(options.appRoot, "bin", "feynman.js"),
|
FEYNMAN_BIN_PATH: resolve(options.appRoot, "bin", "feynman.js"),
|
||||||
|
FEYNMAN_NPM_PREFIX: feynmanNpmPrefixPath,
|
||||||
PANDOC_PATH: process.env.PANDOC_PATH ?? resolveExecutable("pandoc", PANDOC_FALLBACK_PATHS),
|
PANDOC_PATH: process.env.PANDOC_PATH ?? resolveExecutable("pandoc", PANDOC_FALLBACK_PATHS),
|
||||||
PI_HARDWARE_CURSOR: process.env.PI_HARDWARE_CURSOR ?? "1",
|
PI_HARDWARE_CURSOR: process.env.PI_HARDWARE_CURSOR ?? "1",
|
||||||
PI_SKIP_VERSION_CHECK: process.env.PI_SKIP_VERSION_CHECK ?? "1",
|
PI_SKIP_VERSION_CHECK: process.env.PI_SKIP_VERSION_CHECK ?? "1",
|
||||||
MERMAID_CLI_PATH: process.env.MERMAID_CLI_PATH ?? resolveExecutable("mmdc", MERMAID_FALLBACK_PATHS),
|
MERMAID_CLI_PATH: process.env.MERMAID_CLI_PATH ?? resolveExecutable("mmdc", MERMAID_FALLBACK_PATHS),
|
||||||
PUPPETEER_EXECUTABLE_PATH:
|
PUPPETEER_EXECUTABLE_PATH:
|
||||||
process.env.PUPPETEER_EXECUTABLE_PATH ?? resolveExecutable("google-chrome", BROWSER_FALLBACK_PATHS),
|
process.env.PUPPETEER_EXECUTABLE_PATH ?? resolveExecutable("google-chrome", BROWSER_FALLBACK_PATHS),
|
||||||
|
NPM_CONFIG_PREFIX: process.env.NPM_CONFIG_PREFIX ?? feynmanNpmPrefixPath,
|
||||||
|
npm_config_prefix: process.env.npm_config_prefix ?? feynmanNpmPrefixPath,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,14 @@ test("buildPiEnv wires Feynman paths into the Pi environment", () => {
|
|||||||
assert.equal(env.FEYNMAN_SESSION_DIR, "/sessions");
|
assert.equal(env.FEYNMAN_SESSION_DIR, "/sessions");
|
||||||
assert.equal(env.FEYNMAN_BIN_PATH, "/repo/feynman/bin/feynman.js");
|
assert.equal(env.FEYNMAN_BIN_PATH, "/repo/feynman/bin/feynman.js");
|
||||||
assert.equal(env.FEYNMAN_MEMORY_DIR, "/home/.feynman/memory");
|
assert.equal(env.FEYNMAN_MEMORY_DIR, "/home/.feynman/memory");
|
||||||
assert.ok(env.PATH?.startsWith("/repo/feynman/node_modules/.bin:/repo/feynman/.feynman/npm/node_modules/.bin:"));
|
assert.equal(env.FEYNMAN_NPM_PREFIX, "/home/.feynman/npm-global");
|
||||||
|
assert.equal(env.NPM_CONFIG_PREFIX, "/home/.feynman/npm-global");
|
||||||
|
assert.equal(env.npm_config_prefix, "/home/.feynman/npm-global");
|
||||||
|
assert.ok(
|
||||||
|
env.PATH?.startsWith(
|
||||||
|
"/repo/feynman/node_modules/.bin:/repo/feynman/.feynman/npm/node_modules/.bin:/home/.feynman/npm-global/bin:",
|
||||||
|
),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("resolvePiPaths includes the Promise.withResolvers polyfill path", () => {
|
test("resolvePiPaths includes the Promise.withResolvers polyfill path", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user