/**
 * Claude Code session monitor — Phase 1.
 *
 * Watches ~/.claude/projects/<encoded-cwd>/<session-uuid>.jsonl for activity
 * from Claude Code's CLI / IDE clients. Emits an `update` event whenever
 * a session jsonl appears (new) or grows (message). LISA's web server
 * subscribes and broadcasts to /events SSE so the island widget and other
 * surfaces can render a "Claude is busy" indicator.
 *
 * ── PRIVACY CONTRACT ────────────────────────────────────────────────
 *
 *   This module NEVER reads the jsonl message contents. Only:
 *     - filename / directory name (= encoded cwd)
 *     - mtime
 *     - size in bytes
 *
 *   The user's prompts and Claude's replies stay in their files. We do
 *   not parse, log, or transmit them anywhere. Phase 2 might add an
 *   opt-in parser to detect "waiting for permission" semantics — that
 *   will be a separate, explicit decision.
 *
 * ── DEPENDENCIES ────────────────────────────────────────────────────
 *
 *   None added. Uses only `node:fs` (`fs.watch` with `recursive: true`
 *   works on macOS 10.5+ and Windows 10+ — perfect for our target).
 *
 * ── EVENT SEMANTICS ─────────────────────────────────────────────────
 *
 *   - "new"     — a session jsonl appeared we hadn't seen before
 *   - "message" — an existing session jsonl grew (debounced 200ms so a
 *                 fast token stream doesn't fire a flood)
 *   - (Phase 2) "waiting" / "completed" / "error" — needs jsonl parse
 *
 *   Active = mtime within ACTIVE_WINDOW_MS (30 min). listActive()
 *   returns sessions sorted newest-first, capped at MAX_LISTED.
 */
import { EventEmitter } from "node:events";
import { type ClaudeSessionState } from "./parser.js";
import type { SessionActivity } from "../types.js";
/**
 * One row in the in-memory session map. We hold mtime + size only —
 * never any jsonl content.
 */
export interface ClaudeSessionInfo {
    /** Encoded form, e.g. "-Users-oratis-Projects-Adex" */
    projectEncoded: string;
    /** Best-effort display label, e.g. "Adex" */
    projectLabel: string;
    /** UUID (.jsonl basename without extension) */
    sessionId: string;
    /** Last modification time (epoch ms) */
    lastMtime: number;
    /** Size in bytes (rough indicator of message volume) */
    size: number;
    /** Derived state — Phase 2; see parser.ts. */
    state: ClaudeSessionState;
    /** Short reason label for the derived state (debugging / tooltip). */
    stateReason: string;
    /**
     * Phase 3.5: cwd from Claude Code's top-level jsonl `.cwd` field.
     * Used by the island UI for "Open in Finder" / "Copy resume
     * command". Undefined if the jsonl didn't record it.
     */
    cwd?: string;
    /**
     * O2 (Tier-2): structural activity (tool names, files touched, last
     * command, error, tokens). Populated when visibility ≥ "activity".
     * Privacy: structural metadata only — never conversation content.
     */
    activity?: SessionActivity;
}
export interface ClaudeSessionUpdate {
    event: "new" | "message" | "state_changed";
    projectEncoded: string;
    projectLabel: string;
    sessionId: string;
    state: ClaudeSessionState;
    stateReason: string;
    cwd?: string;
    ts: string;
}
type Log = (msg: string) => void;
export declare class ClaudeCodeWatcher extends EventEmitter {
    private sessions;
    private watcher;
    private retryTimer;
    private repollTimer;
    private pendingChanges;
    private readonly log;
    private readonly computeActivity;
    private started;
    constructor(opts?: {
        log?: Log;
        computeActivity?: boolean;
    });
    /** Begin watching. Idempotent. Survives ~/.claude/projects not existing yet. */
    start(): Promise<void>;
    stop(): void;
    /** Sessions modified in the last 30 min, newest first, capped. */
    listActive(): ClaudeSessionInfo[];
    private initialScan;
    private recordExisting;
    private attachWatcher;
    private scheduleRetry;
    /**
     * fs.watch fires the relative path of the changed entry. We debounce
     * to coalesce rapid streaming writes into one `message` event per
     * burst.
     */
    private handleFsEvent;
    private diff;
    private emitUpdate;
    private makeInfo;
    /**
     * Periodic re-evaluation of active sessions' state. The fs.watch
     * stream only fires when the file changes — but the very condition
     * we want to detect (Claude waiting for permission) is "the file
     * STOPPED changing". So we sweep every few seconds: for each session
     * with a recent mtime, re-stat + re-parse + emit `state_changed` if
     * the derived state has flipped.
     *
     * Cheap: stat is O(1), parser reads only the file's tail.
     */
    private startRepollLoop;
    private repollActive;
}
/**
 * `~/.claude/projects/-Users-oratis-Projects-Adex` → "Adex".
 * Heuristic: strip a leading dash, replace remaining dashes with slashes,
 * take the basename. Falls back to the raw encoded form if the result
 * looks broken (no `/`, suspiciously empty).
 */
export declare function decodeProjectLabel(encoded: string): string;
export declare const CLAUDE_PROJECTS_DIR: string;
export {};
//# sourceMappingURL=watcher.d.ts.map