/**
 * `chat watch` core — tail an append-only chat inbox JSONL, emitting only
 * NEW rows (Track T-TR, TR.1). The agent wraps `opensquid chat watch` in the
 * harness `Monitor` tool so each appended message becomes an in-chat event the
 * instant it lands — event-driven push, no cron/interval polling.
 *
 * Design (per docs/tasks/T-telegram-realtime.md):
 *   - NEW-ONLY (L2): start the cursor at the file's current EOF so the backlog
 *     is skipped (still reachable via `chat_poll_inbox`). The file may not exist
 *     yet (created on the first message) — chokidar fires `add` on creation.
 *   - The inbox is read via its ON-DISK CONTRACT, not a shared TS type — the
 *     same WAB.1 design that has `agent_bridge/transport_bridge.ts` re-inline
 *     the row shape rather than import a shared TS type. So
 *     `chat watch` is an independent consumer of the file format, by design.
 *   - READS ARE SERIALIZED: chokidar can fire `change` twice for one write
 *     burst; without serialization two concurrent reads would advance the
 *     cursor over the same bytes and double-emit. We chain reads so exactly one
 *     runs at a time (mirrors transport_bridge.ts's `readChains`).
 *   - awaitWriteFinish coalesces partial-write events; constants match
 *     transport_bridge.ts so both inbox consumers behave identically.
 *
 * Never throws on bad input: a malformed JSONL line is skipped (routed to
 * `onWarn`), the watcher stays up.
 *
 * Imports from: chokidar, node:fs/promises.
 * Imported by: src/runtime/chat/watch_cli.ts.
 */
/**
 * One inbound row as the chat-daemon appends it (mirrors `LegacyInboxRow` in
 * `transport_bridge.ts` — the on-disk contract). `thread_id` is OPTIONAL: DMs
 * have no topic thread, so the formatter must not print `undefined`.
 */
export interface InboxRow {
    id: string;
    thread_id?: string;
    platform: string;
    channel: string;
    sender: string;
    sender_id: string;
    text: string;
    received_at: string;
    enqueued_at: string;
    mentions_bot: boolean;
}
export interface WatchInboxOpts {
    /** Absolute path to the inbox JSONL (see `paths.inboxFile`). */
    inboxFile: string;
    /** Only emit rows whose `mentions_bot` is true (L4 default: false = all). */
    mentionsOnly: boolean;
    /** Line formatter — default `formatRow`, or `JSON.stringify` for `--raw`. */
    format: (row: InboxRow) => string;
    /** Sink for each formatted line. Production: `(l) => process.stdout.write(l + '\n')`. */
    out: (line: string) => void;
    /** Malformed-row + watcher-error sink. Default: swallow. */
    onWarn?: (message: string) => void;
    /** Test seam — force chokidar's polling backend. */
    usePolling?: boolean;
    /** Resolves `watchInbox` + closes the watcher (tests/teardown). */
    signal?: AbortSignal;
}
/**
 * Default human-readable line. DMs have no `thread_id` → fall back to the
 * channel so we never print `[tg undefined]`.
 */
export declare function formatRow(row: InboxRow): string;
/**
 * Tail an append-only JSONL inbox, emitting only rows appended after start.
 * Resolves when `opts.signal` aborts (tests); in production the `Monitor`
 * process lifetime owns the watcher and this never resolves.
 */
export declare function watchInbox(opts: WatchInboxOpts): Promise<void>;
//# sourceMappingURL=watch.d.ts.map