Archived
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.
46 lines
2.0 KiB
TypeScript
46 lines
2.0 KiB
TypeScript
import { isAbsolute, resolve } from "node:path";
|
|
|
|
/**
|
|
* Working-directory normalization boundaries.
|
|
*
|
|
* Cwd strings reach the server from three kinds of sources with different trust:
|
|
*
|
|
* 1. HTTP requests (web UI, federation proxies): normalize strictly with
|
|
* `normalizeRequestCwd` at route parsing. Relative paths are rejected instead
|
|
* of being silently resolved against the daemon's own working directory.
|
|
* 2. Data pi-web writes itself (archive store records): canonicalized on write
|
|
* and on load with `canonicalizeStoredCwd`, so internal `===` comparisons are
|
|
* safe by construction.
|
|
* 3. Data other writers own (Pi session file headers via the SDK): canonicalized
|
|
* on read at the gateway, and compared tolerantly with `cwdPathsEqual` where a
|
|
* raw value can still appear (e.g. runtime cwd of sessions opened from files).
|
|
*
|
|
* Inside these boundaries, plain string equality on cwd values is safe.
|
|
*/
|
|
|
|
/**
|
|
* Strictly normalize a client-supplied working directory at an HTTP boundary.
|
|
* Throws for non-string, empty, or relative input; returns the resolved
|
|
* (separator- and trailing-slash-normalized) absolute path otherwise.
|
|
*/
|
|
export function normalizeRequestCwd(cwd: unknown): string {
|
|
if (typeof cwd !== "string" || cwd === "") throw new Error("cwd is required");
|
|
if (!isAbsolute(cwd)) throw new Error("cwd must be an absolute path");
|
|
return resolve(cwd);
|
|
}
|
|
|
|
/**
|
|
* Leniently canonicalize a working directory loaded from stored data.
|
|
* Absolute paths are resolved to canonical form; anything else (legacy empty or
|
|
* relative values) is preserved as-is so a single bad record cannot fail a whole
|
|
* load, and never silently resolves against this process's working directory.
|
|
*/
|
|
export function canonicalizeStoredCwd(cwd: string): string {
|
|
return isAbsolute(cwd) ? resolve(cwd) : cwd;
|
|
}
|
|
|
|
/** Compare two working-directory paths, tolerating separator and normalization differences (e.g. Windows backslash vs forward slash). */
|
|
export function cwdPathsEqual(a: string, b: string): boolean {
|
|
return resolve(a) === resolve(b);
|
|
}
|