/**
 * SessionManager — reads conversation history directly from the CLI's
 * native JSONL files (e.g. ~/.claude/projects/{encoded-path}/{uuid}.jsonl).
 *
 * No PTY parsing, no ANSI stripping, no heuristics. The JSONL is the single
 * source of truth; ccweb maintains no separate conversation store.
 */
import { EventEmitter } from 'events';
import type { CliTool } from './types';
export interface ChatBlockItem {
    type: 'text' | 'thinking' | 'tool_use' | 'tool_result';
    /** Legacy string form; always populated for backwards compat. For tool_use
     *  it's still `name(args-truncated)`. Rich renderers should prefer `tool` /
     *  `input` / `output` below when present. */
    content: string;
    /** tool_use: tool name (`Bash`, `Edit`, `TodoWrite`, …). */
    tool?: string;
    /** tool_use: structured input with deep string values capped at ~4KB to
     *  protect WS payload size.  Object shape preserved so the frontend can
     *  render tool-specific UIs (TodoWrite checklist, Edit diff, etc.). */
    input?: unknown;
    /** tool_result: full-ish text (up to ~4KB) — `content` keeps the short
     *  legacy truncation for callers that serialize to markdown fences. */
    output?: string;
}
export interface ChatBlock {
    /** Stable block id for dedup between WS replay and HTTP history. Derived
     *  from sha1(jsonlPath + source) so it's idempotent across restarts and
     *  unique per entry. Optional on older code paths; always populated by
     *  session-manager. */
    id?: string;
    role: 'user' | 'assistant';
    timestamp: string;
    blocks: ChatBlockItem[];
}
export type SemanticPhase = 'thinking' | 'tool_use' | 'tool_result' | 'text';
export interface SemanticStatus {
    phase: SemanticPhase;
    detail?: string;
    updatedAt: number;
}
declare class SessionManager extends EventEmitter {
    private watchers;
    private chatListeners;
    private semanticStatus;
    constructor();
    getSemanticStatus(projectId: string): SemanticStatus | null;
    getAllSemanticStatus(): Record<string, SemanticStatus>;
    /** Return the JSONL file path currently being tailed for this project. */
    getJsonlPath(projectId: string): string | null;
    /** Return all parsed ChatBlocks from the project's latest JSONL file.
     *
     *  Resolution order:
     *    1. Active watcher already has `jsonlPath` discovered via hooks → use it.
     *    2. Watcher exists but hasn't discovered the file yet → lazily scan the
     *       adapter's session dir, pick the latest JSONL, cache on the watcher.
     *    3. No watcher (stopped project, user just navigated in) → resolve
     *       project config on-the-fly and pick the latest JSONL. Do NOT
     *       persist to `this.watchers` because a watcher without a PTY
     *       would drift (no hooks, no triggerRead).
     *
     *  This indirection exists because chat history has to be loadable without
     *  a hook ever firing (e.g. immediately after ccweb restart — triggerRead
     *  only runs when Claude Code's hooks call `/api/hooks`).
     */
    getChatHistory(projectId: string): ChatBlock[];
    /** Parse a JSONL/JSON session file into ChatBlocks with stable ids. */
    private parseJsonlFile;
    /** Find the latest JSONL file for a project (single source of truth for
     *  both chat-history HTTP and hook-driven tail paths).
     *
     *  Strategy: pick the newest file (by mtime) in the adapter's session dir.
     *  For adapters that store sessions in a shared tree (e.g. Codex's
     *  date-partitioned dir), use `getSessionFilesForProject` to scope by cwd.
     *
     *  Deliberately has NO startedAt/recency filter — historical requirement
     *  was for "the file THIS session is writing", but that caused HTTP and
     *  WS paths to disagree on which file to read, breaking block-id dedup.
     *  Using "newest" works because Claude --continue updates the mtime of
     *  the continued file, and any new file it creates has the highest mtime.
     *  The caller (triggerRead) handles mid-session file switches by re-
     *  checking on each call.
     */
    private findLatestJsonlForProject;
    registerChatListener(projectId: string, cb: (msg: ChatBlock) => void): void;
    unregisterChatListener(projectId: string, cb: (msg: ChatBlock) => void): void;
    /** Call when a new PTY starts for a project. Registers a watcher so that
     *  subsequent hook-driven `triggerRead()` calls can tail the JSONL. */
    startSession(projectId: string, folderPath: string, cliTool?: CliTool): void;
    /** Stop the session poller for a project (public for cleanup on terminal stop) */
    stopWatcherForProject(projectId: string): void;
    private stopWatcher;
    /** Attach an fs.watch to state.jsonlPath. Detaches any existing watcher
     *  first. Debounces 'change' events and dispatches into readNewLines on
     *  the same code path as hook-driven triggerRead. */
    private attachFsWatch;
    private detachFsWatch;
    /** Called by hooks route on PreToolUse.
     *  Updates semantic status directly from env var — does NOT read JSONL
     *  (JSONL has not been written yet at this point). */
    handleHookPreTool(projectId: string, toolName: string): void;
    /** Called by hooks route on PostToolUse/Stop. Discovers the latest JSONL
     *  file if not already cached, detects mid-session file switches (e.g.
     *  Claude --continue creating a fresh JSONL), then reads new content and
     *  emits block events to chat listeners. */
    triggerRead(projectId: string): void;
    /** Called by hooks route on Stop — clears semantic status before reading final text. */
    clearSemanticStatus(projectId: string): void;
    /** Read new data from the session file and extract messages */
    private readNewLines;
    /** Read whole-file JSON session (Gemini etc.) — re-parse on each trigger,
     *  emit only blocks whose stable id is not yet in `emittedBlockIds`. */
    private readWholeFileSession;
    /** Incremental JSONL reading (Claude, Codex) */
    private readJsonlIncremental;
}
export declare const sessionManager: SessionManager;
export {};
//# sourceMappingURL=session-manager.d.ts.map