import type { SessionFileMeta } from './session-filter.js'; /** One message in the reconstructed conversation. */ export interface ConversationMessage { role: string; content: string; } /** * An Anthropic-shaped envelope for ONE whole Claude Code session (a conversation). The server's * `claude_code` ingestor recognises it by the synthetic `claudecode://session/` url, * stores the full back-and-forth (the server already treats a multi-message request as one "chat" * log), and deduplicates on the session id. `request_body.messages` is the conversation — including * tool calls and tool results, serialised into each message's text so nothing is lost; * `response_body` is the final assistant turn; `response_body.usage` is the session's summed tokens. */ export interface CaptureEnvelope { url: string; method: string; status_code: number; request_body: { model?: string; messages: ConversationMessage[]; }; response_body: { id: string; type: string; role: string; model?: string; content: unknown; usage?: unknown; }; /** Number of assistant turns in this session — compared against state to detect growth. */ turnCount: number; /** The session's working directory, taken from the transcript's first line carrying a * non-empty string `cwd`. Undefined when no line has one — never guessed. */ projectPath?: string; } export interface ScanResult { envelopes: CaptureEnvelope[]; sessionCount: number; /** Number of session files rejected by the caller's preFilter — skipped without being read. */ filteredOut: number; /** False when the scan directory could not be read and the error was swallowed. The caller must * not advance its mtime cutoff in this case — doing so would permanently hide pre-existing files * whose mtimes predate the new cutoff, since the turn-count guard never sees them if they are * never read. */ ok: boolean; } export declare function defaultProjectsDir(): string; /** * Parse one transcript's raw text (newline-delimited JSON) into a SINGLE session envelope holding * the whole conversation — one log per session, not one per turn. Returns `null` when the transcript * contains no assistant turns. Pure function (no filesystem) so it is easy to unit test. * * Real transcripts split a single assistant API call across MULTIPLE lines — one per content block * (thinking / text / tool_use) — and repeat the identical `usage` on every line. We therefore merge * lines that share a `requestId` into one assistant message and count each turn (and its tokens) * exactly once, matching benchmark/lib/transcript.mjs. */ export declare function parseTranscript(content: string, sessionId: string): CaptureEnvelope | null; /** * Find every Claude Code transcript under `projectsDir` (default `~/.claude/projects`) and build one * conversation envelope per session. A missing directory simply yields zero sessions. * * When `sinceTime` is given, files whose last-modified time is older than it are skipped entirely * (not even read) — they cannot have grown since the last sync. `sessionCount` therefore counts only * the files actually examined this run, so it reflects the work done rather than the whole corpus. * * When `preFilter` is given it runs on each file's metadata (id, project folder, mtime) BEFORE the * file is read; a rejected file is counted in `filteredOut` and its content never leaves disk. */ export declare function scanSessions(options?: { projectsDir?: string; sinceTime?: Date; preFilter?: (meta: SessionFileMeta) => boolean; }): Promise; /** The session id this envelope represents — used as the local dedup key. */ export declare function sessionIdOf(envelope: CaptureEnvelope): string; //# sourceMappingURL=claude-scanner.d.ts.map