fix(pi): add snap node compatibility diagnostics and documentation

- Added detailed error logging to detect snap node compatibility issues
- When Pi process exits with code 1, log helpful diagnostic info including node path
- Add hint to check for snap node and reinstall via apt/nvm
- Create SNAP_NODE_COMPATIBILITY.md with full troubleshooting guide
- Document root cause: snap node has file descriptor incompatibility with Bun.spawn stdin pipes
- Provide clear installation instructions for NodeSource and nvm alternatives
This commit is contained in:
2026-03-04 01:45:36 +00:00
parent 72d1341cbc
commit ef13f96d36
34 changed files with 2394 additions and 1466 deletions
+8 -10
View File
@@ -91,7 +91,10 @@ export async function sendAndAwait(params: SendAndAwaitParams): Promise<SendAndA
const lockPromise = new Promise<void>((resolve) => {
releaseLock = resolve;
});
sessionLocks.set(sessionId, existing.then(() => lockPromise));
sessionLocks.set(
sessionId,
existing.then(() => lockPromise),
);
await existing;
@@ -291,23 +294,18 @@ async function doSend(sessionId: string, params: SendAndAwaitParams): Promise<Se
(async () => {
try {
if (!session.piProcess) {
let spawnOptions: { sessionFile?: string } | undefined;
let spawnOptions: { sessionFile?: string; username?: string } | undefined;
if (session.messages.length > 0) {
await storage.saveSession(homeDir, sessionId, session.meta, session.messages);
const hostPath = await storage.getSessionFilePath(homeDir, sessionId);
if (hostPath) {
// Remap host path to container path
const containerHome = `/home/${username}`;
const sessionsPrefix = join(homeDir, '.pi', 'agent', 'sessions');
const relativePart = hostPath.slice(sessionsPrefix.length);
spawnOptions = { sessionFile: `${containerHome}/.pi/agent/sessions${relativePart}` };
spawnOptions = { sessionFile: hostPath, username };
}
}
if (!spawnOptions) spawnOptions = { username };
const dispatcher = createDispatcher(sessionId);
const sandbox = { userId, username, email, homeDir };
session.piProcess = await piBridge.spawnPi(cwd, model!, userId, email, dispatcher, sandbox, spawnOptions);
session.sandboxed = true;
session.piProcess = await piBridge.spawnPi(cwd, model!, userId, email, dispatcher, spawnOptions);
const proc = session.piProcess;
proc.exited.then(() => {