import { lstat } from "node:fs/promises"; import { join } from "node:path"; import type { DurablePrincipal, DurablePrincipalAuthority, DurablePrincipalCoordinates, NewDurablePrincipalRequest, } from "../host-contracts.ts"; import { resolveBookKeyFromGit } from "../activation-ledger-git.ts"; import { resolveActivationLedgerHome } from "../activation-ledger-topology.ts"; import { roleRunPlacement } from "../role-run-placement.ts"; type PiDurablePrincipal = DurablePrincipal & { readonly sessionDirectory: string; readonly sessionFile: string; }; function encode(coordinates: DurablePrincipalCoordinates): PiDurablePrincipal { return coordinates as PiDurablePrincipal; } export function issuePiDurablePrincipalCoordinates( request: NewDurablePrincipalRequest, ): DurablePrincipalCoordinates & { readonly ledgerHome: string; readonly bookKey: string; readonly runDirectory: string; } { const ledgerHome = resolveActivationLedgerHome(request.home); const bookKey = resolveBookKeyFromGit(request.cwd); const placement = roleRunPlacement(ledgerHome, { bookKey, subject: { unbound: true }, runId: request.runId, role: request.role, }); return { ledgerHome, bookKey, ...placement, }; } /** Pi's durable-principal codec and availability authority. */ export const piDurablePrincipalAuthority: DurablePrincipalAuthority = { issue(request: NewDurablePrincipalRequest): DurablePrincipal { const coordinates = issuePiDurablePrincipalCoordinates(request); return encode({ sessionDirectory: coordinates.sessionDirectory, sessionFile: coordinates.sessionFile, }); }, seal(coordinates: DurablePrincipalCoordinates): DurablePrincipal { return encode({ sessionDirectory: coordinates.sessionDirectory, sessionFile: coordinates.sessionFile, }); }, decode(value: unknown): DurablePrincipalCoordinates { const record = value as Partial | null; if (record === null || typeof record !== "object") { throw new Error("durable principal payload is missing"); } if (typeof record.sessionDirectory !== "string" || record.sessionDirectory.trim() === "") { throw new Error("durable principal session directory is missing"); } return { sessionDirectory: record.sessionDirectory, sessionFile: typeof record.sessionFile === "string" && record.sessionFile.trim() !== "" ? record.sessionFile : join(record.sessionDirectory, "session.jsonl"), }; }, async isAvailable(principal: DurablePrincipal): Promise { const { sessionFile } = this.decode(principal); try { const stat = await lstat(sessionFile); return stat.isFile() && !stat.isSymbolicLink(); } catch { return false; } }, };