refactor(agent): harden harness session semantics

This commit is contained in:
Mario Zechner
2026-05-16 00:32:16 +02:00
parent a8af0b5e99
commit 4f40f62b7b
23 changed files with 1112 additions and 873 deletions
@@ -1,4 +1,11 @@
import type { SessionMetadata, SessionStorage, SessionTreeEntry } from "../types.js";
import {
type FileError,
type Result,
SessionError,
type SessionMetadata,
type SessionStorage,
type SessionTreeEntry,
} from "../types.js";
import { Session } from "./session.js";
import { uuidv7 } from "./uuid.js";
@@ -14,6 +21,14 @@ export function toSession<TMetadata extends SessionMetadata>(storage: SessionSto
return new Session(storage);
}
export function getFileSystemResultOrThrow<TValue>(result: Result<TValue, FileError>, message: string): TValue {
if (!result.ok) {
const code = result.error.code === "not_found" ? "not_found" : "storage";
throw new SessionError(code, `${message}: ${result.error.message}`, result.error);
}
return result.value;
}
export async function getEntriesToFork(
storage: SessionStorage,
options: { entryId?: string; position?: "before" | "at" },
@@ -21,14 +36,14 @@ export async function getEntriesToFork(
if (!options.entryId) return storage.getEntries();
const target = await storage.getEntry(options.entryId);
if (!target) {
throw new Error(`Entry ${options.entryId} not found`);
throw new SessionError("invalid_fork_target", `Entry ${options.entryId} not found`);
}
let effectiveLeafId: string | null;
if ((options.position ?? "before") === "at") {
effectiveLeafId = target.id;
} else {
if (target.type !== "message" || target.message.role !== "user") {
throw new Error(`Entry ${options.entryId} is not a user message`);
throw new SessionError("invalid_fork_target", `Entry ${options.entryId} is not a user message`);
}
effectiveLeafId = target.parentId;
}