fix: list and open sessions across project directories

Sessions outside the server's launch directory were invisible and returned
404 on open, leaving the model picker empty. List without the SDK's
process-cwd filter and normalize working directories at the API boundary and
when reading stored session data, tolerating separator/normalization
differences (including Windows backslash vs forward slash). Requires Pi
coding agent SDK 0.78.0 or newer.
This commit is contained in:
Federico Jaramillo Martinez
2026-06-13 11:40:47 +02:00
parent 38cf334c40
commit c0d12222a2
14 changed files with 2342 additions and 2261 deletions
+11 -2
View File
@@ -3,6 +3,7 @@ import { readdir } from "node:fs/promises";
import { homedir } from "node:os";
import { dirname, isAbsolute, join, resolve } from "node:path";
import { getAgentDir, SessionManager, SettingsManager } from "@earendil-works/pi-coding-agent";
import { canonicalizeStoredCwd, cwdPathsEqual } from "../workingDirectory.js";
import type { PiSessionListEntry, PiSessionManager, PiSessionManagerGateway } from "./piSessionService.js";
export const PI_SESSION_DIR_ENV = "PI_CODING_AGENT_SESSION_DIR";
@@ -77,7 +78,13 @@ class SettingsAwarePiSessionManagerGateway implements PiSessionManagerGateway {
}
export async function listSessionsInDir(sessionDir: string): Promise<PiSessionListEntry[]> {
return SessionManager.list("", sessionDir);
// listAll(sessionDir) lists without the SDK's internal cwd filter, which would
// otherwise compare against this process's cwd and drop other projects' sessions.
// Cwd filtering is applied explicitly by filterSessionsForCwd where needed.
// Session file headers are written by external tools (Pi CLI, SDK consumers),
// so their cwd is canonicalized here before it enters pi-web.
const sessions = await SessionManager.listAll(sessionDir);
return sessions.map((session) => ({ ...session, cwd: canonicalizeStoredCwd(session.cwd) }));
}
export async function listSessionsInDefaultPiStore(storeRoot = defaultPiSessionsRoot()): Promise<PiSessionListEntry[]> {
@@ -94,7 +101,9 @@ export async function listSessionsInDefaultPiStore(storeRoot = defaultPiSessions
}
export function filterSessionsForCwd(sessions: readonly PiSessionListEntry[], cwd: string): PiSessionListEntry[] {
return sessions.filter((session) => session.cwd === cwd);
// Sessions with an empty cwd (old session files) are excluded: resolve("") would
// resolve to this process's cwd and produce false matches.
return sessions.filter((session) => session.cwd !== "" && cwdPathsEqual(session.cwd, cwd));
}
export function defaultPiSessionsRoot(agentDir = getAgentDir()): string {