feat(persistence): add persistence hooks to event services
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user