diff --git a/packages/agent/src/harness/experimental/session/memory.ts b/packages/agent/src/harness/experimental/session/memory.ts index a79085145..2c212dc0a 100644 --- a/packages/agent/src/harness/experimental/session/memory.ts +++ b/packages/agent/src/harness/experimental/session/memory.ts @@ -49,7 +49,6 @@ export class InMemorySessionStorage implements SessionStorage { private readonly usedIds = new Set(); private readonly entries: Entry[] = []; private readonly entriesById = new Map(); - private readonly laneByEntryId = new Map(); private readonly records: LaneRecord[] = []; private readonly lanes = new Map([["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 { 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(newEntry: ProvisionedEntry, lane: string): Promise { @@ -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}`); diff --git a/packages/agent/src/harness/experimental/session/testing/conformance.ts b/packages/agent/src/harness/experimental/session/testing/conformance.ts index 9f1f720ea..62d76627a 100644 --- a/packages/agent/src/harness/experimental/session/testing/conformance.ts +++ b/packages/agent/src/harness/experimental/session/testing/conformance.ts @@ -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 }, ], ); }), diff --git a/packages/agent/src/harness/experimental/session/types.ts b/packages/agent/src/harness/experimental/session/types.ts index acba16e06..066e960b0 100644 --- a/packages/agent/src/harness/experimental/session/types.ts +++ b/packages/agent/src/harness/experimental/session/types.ts @@ -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 };