/** * hmem v2 — the always-on live summarizer (the loop behind the DI seam). * * Imports `entries` + `events` (and reaches the `sessions`/`segment_summaries` * tables via raw SQL) and wires `flushSegment` as the `onSegmentClose` hook when * the sessions API is constructed (D5: `sessions.ts` never imports this module). * * The summarizer itself is injected (`Summarizer = (events) => string | * Promise`) so the loop is deterministically unit-testable with a stub; * the real Haiku adapter lives in `./anthropic.ts`. Each binding segment owns one * rolling-summary node (a `#session-summary` child of the segment's project) plus a * one-line `sessions.summary`; re-summarizing rebuilds that node *in place* keyed * by `(session_id, from_seq)`, never creating a duplicate (scenario 3). * * Sync/async contract: when the injected `summarize` returns a string the whole * persist path runs synchronously (so a boundary flush completes within `bind`); * when it returns a Promise the persist is chained and a Promise is returned. */ import type Database from 'better-sqlite3'; import type { EntriesApi } from '../store/entries.js'; import type { EventsApi } from '../store/events.js'; import type { ClosedSegment, EventRow } from '../store/types.js'; export type Summarizer = (events: EventRow[]) => string | Promise; export interface SummarizerDeps { db: Database.Database; entries: EntriesApi; events: EventsApi; /** Optional sessions API; when absent the one-line summary is written via raw SQL. */ sessions?: { updateSessionSummary(session_id: string, summary: string, node_uid: string): void; }; summarize: Summarizer; cadence: number; } export interface SummarizerApi { resummarizeSegment(session_id: string, fromSeq: number, toSeq: number): void | Promise; flushSegment(c: ClosedSegment): void | Promise; maybeCheckpoint(session_id: string): void | Promise; } export declare function createSummarizer(deps: SummarizerDeps): SummarizerApi;