fix: bind pi runtime config at spawn
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import {
|
||||
closeSync, constants, fstatSync, lstatSync, openSync, readFileSync,
|
||||
chmodSync, closeSync, constants, fstatSync, lstatSync, mkdtempSync, openSync,
|
||||
readFileSync, readdirSync, rmSync, symlinkSync, writeFileSync, type Dirent,
|
||||
} from "node:fs";
|
||||
import { homedir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { homedir, tmpdir } from "node:os";
|
||||
import { join, resolve } from "node:path";
|
||||
|
||||
const MAX_AGENT_CONFIG_BYTES = 1024 * 1024;
|
||||
|
||||
@@ -55,13 +56,15 @@ export function validateDeclarativePiConfig(raw: string): void {
|
||||
assertDeclarativePiConfig(parsePiConfigJson(raw));
|
||||
}
|
||||
|
||||
export function readConfiguredPiAgentFile(name: "auth.json"): string;
|
||||
export function readConfiguredPiAgentFile(name: "models.json", optional: true): string | undefined;
|
||||
export function readConfiguredPiAgentFile(
|
||||
function configuredPiAgentDir(): string {
|
||||
return resolve(process.env.PI_CODING_AGENT_DIR ?? join(homedir(), ".pi", "agent"));
|
||||
}
|
||||
|
||||
function readPiAgentFile(
|
||||
configuredAgentDir: string,
|
||||
name: "auth.json" | "models.json",
|
||||
optional = false,
|
||||
optional: boolean,
|
||||
): string | undefined {
|
||||
const configuredAgentDir = process.env.PI_CODING_AGENT_DIR ?? join(homedir(), ".pi", "agent");
|
||||
const path = join(configuredAgentDir, name);
|
||||
let fd: number | undefined;
|
||||
try {
|
||||
@@ -85,3 +88,74 @@ export function readConfiguredPiAgentFile(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function readConfiguredPiAgentFile(name: "auth.json"): string;
|
||||
export function readConfiguredPiAgentFile(name: "auth.json", optional: true): string | undefined;
|
||||
export function readConfiguredPiAgentFile(name: "models.json", optional: true): string | undefined;
|
||||
export function readConfiguredPiAgentFile(
|
||||
name: "auth.json" | "models.json",
|
||||
optional = false,
|
||||
): string | undefined {
|
||||
return readPiAgentFile(configuredPiAgentDir(), name, optional);
|
||||
}
|
||||
|
||||
export interface PiRuntimeAgentSnapshot {
|
||||
agentDir: string;
|
||||
sessionDir: string;
|
||||
cleanup: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind a session Pi process to the exact managed auth/model bytes validated at spawn time.
|
||||
* Other agent resources remain live through symlinks, while session storage stays persistent.
|
||||
*/
|
||||
export function createPiRuntimeAgentSnapshot(): PiRuntimeAgentSnapshot {
|
||||
const sourceAgentDir = configuredPiAgentDir();
|
||||
const auth = readPiAgentFile(sourceAgentDir, "auth.json", true);
|
||||
const models = readPiAgentFile(sourceAgentDir, "models.json", true);
|
||||
if (auth !== undefined) validateDeclarativePiConfig(auth);
|
||||
if (models !== undefined) validateDeclarativePiConfig(models);
|
||||
|
||||
let snapshotDir: string | undefined;
|
||||
try {
|
||||
snapshotDir = mkdtempSync(join(tmpdir(), "thoth-pi-runtime-agent-"));
|
||||
chmodSync(snapshotDir, 0o700);
|
||||
let entries: Dirent[];
|
||||
try {
|
||||
entries = readdirSync(sourceAgentDir, { withFileTypes: true });
|
||||
} catch (error) {
|
||||
if ((error as NodeJS.ErrnoException)?.code !== "ENOENT") throw error;
|
||||
entries = [];
|
||||
}
|
||||
for (const entry of entries) {
|
||||
if (entry.name === "auth.json" || entry.name === "models.json") continue;
|
||||
symlinkSync(
|
||||
join(sourceAgentDir, entry.name),
|
||||
join(snapshotDir, entry.name),
|
||||
entry.isDirectory() ? (process.platform === "win32" ? "junction" : "dir") : "file",
|
||||
);
|
||||
}
|
||||
if (auth !== undefined) {
|
||||
writeFileSync(join(snapshotDir, "auth.json"), auth, { flag: "wx", mode: 0o600 });
|
||||
}
|
||||
if (models !== undefined) {
|
||||
writeFileSync(join(snapshotDir, "models.json"), models, { flag: "wx", mode: 0o600 });
|
||||
}
|
||||
} catch {
|
||||
if (snapshotDir !== undefined) {
|
||||
try { rmSync(snapshotDir, { recursive: true, force: true }); } catch { /* sanitized */ }
|
||||
}
|
||||
throw new PiManagedConfigError();
|
||||
}
|
||||
|
||||
let cleaned = false;
|
||||
return {
|
||||
agentDir: snapshotDir,
|
||||
sessionDir: process.env.PI_CODING_AGENT_SESSION_DIR || join(sourceAgentDir, "sessions"),
|
||||
cleanup: () => {
|
||||
if (cleaned) return;
|
||||
cleaned = true;
|
||||
try { rmSync(snapshotDir, { recursive: true, force: true }); } catch { /* sanitized */ }
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user