/** * The system chat's HISTORY (DES-SYSTEM-CHAT "Crew" §1, api-types 0.137.0). * * A chat's live transcript (`chat-transcripts.ts`) lives as long as the chat. The history keeps it * after: every chat opened on this daemon gets an entry (`/chats/history/.json`: * who opened it, where, which CLI, when, open or closed), and when the chat ends — Close, the * engine's idle or pool-cap close, a daemon restart — its transcript is COPIED beside the entry * (`.jsonl`). Only `DELETE /chats/:id` removes an entry, with its transcript and attachments. * * Title, message count and last activity are DERIVED from the transcript when read (the live file * for an open chat, the kept copy for a closed one), never stored twice. * * A chat id is minted by the client and may be reused. Opening an id whose history is closed moves * the old entry to `--` first, so a reuse never overwrites a past conversation. */ import type { ChatHistoryEntry, ChatStartedOn, ChatTranscriptRecord } from '../core/types.js'; import type { ChatAttachmentStore } from './chat-attachments.js'; export declare const CHAT_HISTORY_DEFAULT_LIMIT = 20; export declare const CHAT_HISTORY_MAX_LIMIT = 100; export declare function defaultChatHistoryDir(): string; /** The transcript reader the history derives from (the live store). */ export interface TranscriptReader { /** `/.jsonl` of the LIVE transcript, or null for a refused id. */ pathOf(chatId: string): string | null; } /** The first operator message, whitespace-collapsed and cut at {@link TITLE_MAX} characters. */ export declare function titleOf(records: readonly ChatTranscriptRecord[]): string; export declare function decodeCursor(cursor: string): { updatedAt: number; id: string; } | null; export declare class ChatHistoryStore { private readonly transcripts; private readonly attachments; readonly dir: string; private readonly now; constructor(transcripts: TranscriptReader, attachments: ChatAttachmentStore | null, opts?: { dir?: string; now?: () => number; }); private valid; private metaPath; private keptPath; private ensureDir; private read; private write; /** A chat was opened: a fresh entry. A CLOSED entry under the same id is kept under a new id. */ opened(id: string, opts: { startedOn?: ChatStartedOn | undefined; cli: string | null; actorId: string | null; }): void; /** An archive id for a reused chat id that names NOTHING yet — no entry, no kept transcript, no * attachments (a client may have chosen `x--T` itself; it is never overwritten). */ private freeArchiveId; /** The chat's answering CLI became known (the path's primary agent). */ setCli(id: string, cli: string): void; /** The chat ended (any reason): keep its transcript. Idempotent; no entry ⇒ nothing (a chat this * daemon never opened). */ closed(id: string): void; /** `DELETE /chats/:id`: the entry, its kept transcript and its attachments go. */ remove(id: string): void; /** Daemon boot: every entry still `open` belonged to the previous process — close it (keeping its * transcript) BEFORE the live transcripts are cleared. */ closeOrphaned(): number; /** The records of a chat: the live transcript while open, the kept copy once closed. */ messages(id: string): ChatTranscriptRecord[] | null; private sourceOf; private updatedAtOf; private view; /** Whether `actorId` may see the entry: entries are per opener under `auth: required` * (`actorId` null = local mode, everyone). An unknown id is nobody's. */ visibleTo(id: string, actorId: string | null): boolean; /** One entry, or null. `liveCli`: the answering CLI the live path knows now. */ entry(id: string, liveCli?: string | null, isLive?: (id: string) => boolean): ChatHistoryEntry | null; /** A page of entries, newest activity first. */ list(opts: { limit?: number; cursor?: string | null; status?: 'open' | 'closed' | 'all'; actorId?: string | null; liveCli?: (id: string) => string | null; /** Whether the chat is held live by this daemon now. */ isLive?: (id: string) => boolean; }): { items: ChatHistoryEntry[]; nextCursor: string | null; }; } //# sourceMappingURL=chat-history.d.ts.map