feat(persistence): add persistence hooks to event services

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
root
2026-03-09 14:25:16 +00:00
parent 0fdf6c95af
commit 552d5fcafb
4 changed files with 59 additions and 0 deletions
+13
View File
@@ -18,14 +18,18 @@ export interface InventionTimeline {
getAll(): InventionEntry[];
getSummaries(): InventionSummary[];
countByEntity(entityId: EntityId): number;
setPersistence(saveFn: (entry: InventionEntry) => void): void;
loadFromPersistence(loadedEntries: InventionEntry[]): void;
}
export function createInventionTimeline(): InventionTimeline {
const entries: InventionEntry[] = [];
let persistFn: ((entry: InventionEntry) => void) | null = null;
return {
record(entry: InventionEntry): void {
entries.push(entry);
if (persistFn) persistFn(entry);
},
getAll(): InventionEntry[] {
@@ -48,5 +52,14 @@ export function createInventionTimeline(): InventionTimeline {
countByEntity(entityId: EntityId): number {
return entries.filter(e => e.inventorEntityId === entityId).length;
},
setPersistence(saveFn: (entry: InventionEntry) => void): void {
persistFn = saveFn;
},
loadFromPersistence(loadedEntries: InventionEntry[]): void {
entries.length = 0;
entries.push(...loadedEntries);
},
};
}
+13
View File
@@ -3,12 +3,15 @@ import type { StockpileLogEntry } from '@dflike/shared';
export interface StockpileLog {
record(entry: StockpileLogEntry): void;
getRecent(): StockpileLogEntry[];
setPersistence(saveFn: (entry: StockpileLogEntry) => void): void;
loadFromPersistence(entries: StockpileLogEntry[]): void;
}
const MAX_ENTRIES = 50;
export function createStockpileLog(): StockpileLog {
const entries: StockpileLogEntry[] = [];
let persistFn: ((entry: StockpileLogEntry) => void) | null = null;
return {
record(entry: StockpileLogEntry): void {
@@ -16,10 +19,20 @@ export function createStockpileLog(): StockpileLog {
if (entries.length > MAX_ENTRIES) {
entries.shift();
}
if (persistFn) persistFn(entry);
},
getRecent(): StockpileLogEntry[] {
return [...entries];
},
setPersistence(saveFn: (entry: StockpileLogEntry) => void): void {
persistFn = saveFn;
},
loadFromPersistence(loadedEntries: StockpileLogEntry[]): void {
entries.length = 0;
entries.push(...loadedEntries);
},
};
}
+17
View File
@@ -10,11 +10,14 @@ export interface EventMemoryService {
preferEntityId?: EntityId;
}): MemoryEvent[];
onEventRecorded: ((entityId: EntityId, event: MemoryEvent) => void) | null;
setPersistence(saveFn: (entityId: EntityId, event: MemoryEvent) => void): void;
loadFromPersistence(allEvents: Map<EntityId, MemoryEvent[]>): void;
}
export function createEventMemoryService(maxEvents = 50): EventMemoryService {
const buffers = new Map<EntityId, MemoryEvent[]>();
let nextId = 1;
let persistFn: ((entityId: EntityId, event: MemoryEvent) => void) | null = null;
function getBuffer(entityId: EntityId): MemoryEvent[] {
let buf = buffers.get(entityId);
@@ -43,6 +46,7 @@ export function createEventMemoryService(maxEvents = 50): EventMemoryService {
buf.shift();
}
if (persistFn) persistFn(entityId, event);
service.onEventRecorded?.(entityId, event);
return event;
@@ -102,6 +106,19 @@ export function createEventMemoryService(maxEvents = 50): EventMemoryService {
return scored.slice(0, opts.maxCount).map((s) => s.event);
},
setPersistence(saveFn: (entityId: EntityId, event: MemoryEvent) => void): void {
persistFn = saveFn;
},
loadFromPersistence(allEvents: Map<EntityId, MemoryEvent[]>): void {
for (const [entityId, events] of allEvents) {
buffers.set(entityId, [...events]);
for (const e of events) {
if (e.id >= nextId) nextId = e.id + 1;
}
}
},
};
return service;
+16
View File
@@ -22,6 +22,8 @@ export interface NarrationService {
getEventsForEntity(entityId: EntityId): NarrationEvent[];
onEventUpdated: ((event: NarrationEvent) => void) | null;
onEventCreated: ((event: NarrationEvent) => void) | null;
setPersistence(saveFn: (event: NarrationEvent) => void): void;
loadFromPersistence(events: NarrationEvent[]): void;
}
const MAX_BUFFER_SIZE = 50;
@@ -29,6 +31,7 @@ const MAX_BUFFER_SIZE = 50;
export function createNarrationService(llmService: LlmService): NarrationService {
const buffer: NarrationEvent[] = [];
let nextId = 1;
let persistFn: ((event: NarrationEvent) => void) | null = null;
const service: NarrationService = {
onEventUpdated: null,
@@ -56,6 +59,7 @@ export function createNarrationService(llmService: LlmService): NarrationService
buffer.shift();
}
if (persistFn) persistFn(event);
service.onEventCreated?.(event);
const shouldQueueLlm =
@@ -96,6 +100,18 @@ export function createNarrationService(llmService: LlmService): NarrationService
(e) => e.entityIds[0] === entityId || e.entityIds[1] === entityId,
);
},
setPersistence(saveFn: (event: NarrationEvent) => void): void {
persistFn = saveFn;
},
loadFromPersistence(events: NarrationEvent[]): void {
buffer.length = 0;
buffer.push(...events);
if (events.length > 0) {
nextId = Math.max(...events.map(e => e.id)) + 1;
}
},
};
return service;