refactor(agent): split harness experimental changes (#7587)

This commit is contained in:
Cristina Poncela Cubeiro 2026-08-04 10:34:15 +02:00 • committed by GitHub
parent 0524d6897f
commit cd20a8d2e5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 13 additions and 30 deletions

View file

@ -49,7 +49,6 @@ export class InMemorySessionStorage implements SessionStorage {
private readonly usedIds = new Set<string>();
private readonly entries: Entry[] = [];
private readonly entriesById = new Map<string, Entry>();
private readonly laneByEntryId = new Map<string, string>();
private readonly records: LaneRecord[] = [];
private readonly lanes = new Map<string, string | null>([["main", null]]);
private readonly log: LogItem[] = [];
@ -93,21 +92,13 @@ export class InMemorySessionStorage implements SessionStorage {
for (const sourceEntry of copiedEntries) {
const entry = structuredClone(sourceEntry);
entry.seq = storage.nextSequence();
const lane = options.scope === "tree" ? this.requireEntryLane(sourceEntry.id) : "main";
storage.entries.push(entry);
storage.entriesById.set(entry.id, entry);
storage.laneByEntryId.set(entry.id, lane);
storage.usedIds.add(entry.id);
storage.log.push({ kind: "entry", seq: entry.seq, lane, entry });
storage.log.push({ kind: "entry", seq: entry.seq, entry });
}
for (const [lane, leafId] of options.scope === "tree" ? this.lanes : []) {
storage.log.push({
kind: "lane",
seq: storage.nextSequence(),
lane,
action: lane === "main" ? "move" : "create",
leafId,
});
storage.log.push({ kind: "lane", seq: storage.nextSequence(), lane, leafId });
}
if (this.name !== undefined) {
storage.name = this.name;
@ -133,14 +124,14 @@ export class InMemorySessionStorage implements SessionStorage {
if (this.lanes.has(lane)) throw new SessionError("already_exists", `Lane already exists: ${lane}`);
this.validateTarget(at);
this.lanes.set(lane, at);
this.log.push({ kind: "lane", seq: this.nextSequence(), lane, action: "create", leafId: at });
this.log.push({ kind: "lane", seq: this.nextSequence(), lane, leafId: at });
}
async moveLane(lane: string, to: string | null): Promise<void> {
this.requireLane(lane);
this.validateTarget(to);
this.lanes.set(lane, to);
this.log.push({ kind: "lane", seq: this.nextSequence(), lane, action: "move", leafId: to });
this.log.push({ kind: "lane", seq: this.nextSequence(), lane, leafId: to });
}
async appendEntry<TEntry extends Entry>(newEntry: ProvisionedEntry<TEntry>, lane: string): Promise<TEntry> {
@ -151,9 +142,8 @@ export class InMemorySessionStorage implements SessionStorage {
this.usedIds.add(entry.id);
this.entries.push(entry);
this.entriesById.set(entry.id, entry);
this.laneByEntryId.set(entry.id, lane);
this.lanes.set(lane, entry.id);
this.log.push({ kind: "entry", seq: entry.seq, lane, entry });
this.log.push({ kind: "entry", seq: entry.seq, entry });
if (entry.type === "message") this.stats.messageCount += 1;
return structuredClone(entry);
}
@ -265,14 +255,6 @@ export class InMemorySessionStorage implements SessionStorage {
return leafId;
}
private requireEntryLane(entryId: string): string {
const lane = this.laneByEntryId.get(entryId);
if (lane === undefined) {
throw new SessionError("invalid_entry", `Entry has no originating lane: ${entryId}`);
}
return lane;
}
private validateTarget(targetId: string | null): void {
if (targetId !== null && !this.entriesById.has(targetId)) {
throw new SessionError("not_found", `Entry not found: ${targetId}`);

View file

@ -155,9 +155,9 @@ export function createSessionBackendConformance(
await session.moveLane("main", null);
deepStrictEqual(await session.getLanes(), [{ lane: "main", leafId: null }]);
deepStrictEqual(await session.getLog(), [
{ kind: "entry", seq: 1, lane: "main", entry: root },
{ kind: "entry", seq: 1, entry: root },
{ kind: "record", seq: 2, record: finished },
{ kind: "lane", seq: 3, lane: "main", action: "move", leafId: null },
{ kind: "lane", seq: 3, lane: "main", leafId: null },
]);
await rejectsWithCode(session.moveLane("main", "missing"), "not_found");
@ -583,7 +583,7 @@ export function createSessionBackendConformance(
if (stored?.type !== "message") throw new Error("Expected message entry");
strictEqual(stored.terminate, true);
deepStrictEqual(await session.findEntries(), [entry]);
deepStrictEqual(await session.getLog(), [{ kind: "entry", seq: entry.seq, lane: "main", entry }]);
deepStrictEqual(await session.getLog(), [{ kind: "entry", seq: entry.seq, entry }]);
}),
createCase(
@ -781,8 +781,8 @@ export function createSessionBackendConformance(
deepStrictEqual(
(await fork.getLog()).filter((item) => item.kind === "lane"),
[
{ kind: "lane", seq: 4, lane: "main", action: "move", leafId: mainChild },
{ kind: "lane", seq: 5, lane: "thread", action: "create", leafId: threadChild },
{ kind: "lane", seq: 4, lane: "main", leafId: mainChild },
{ kind: "lane", seq: 5, lane: "thread", leafId: threadChild },
],
);
}),

View file

@ -1,4 +1,5 @@
import type { StopReason, Usage } from "@earendil-works/pi-ai";
import "../../messages.ts";
import type { AgentMessage } from "../../../types.ts";
import type { Session } from "./session.ts";
@ -263,9 +264,9 @@ export interface LanePointer {
}
export type LogItem =
| { kind: "entry"; seq: number; lane: string; entry: Entry }
| { kind: "entry"; seq: number; entry: Entry }
| { kind: "record"; seq: number; record: LaneRecord }
| { kind: "lane"; seq: number; lane: string; action: "create" | "move"; leafId: string | null }
| { kind: "lane"; seq: number; lane: string; leafId: string | null }
| { kind: "fact"; seq: number; fact: "name"; name: string }
| { kind: "fact"; seq: number; fact: "label"; targetId: string; label: string | undefined };