import type { DaemonSession } from './types.js';
import type { Session } from '../types.js';
export type SessionReplyTarget = {
    mode: 'plain';
    chatId: string;
} | {
    mode: 'thread';
    rootMessageId: string;
};
export declare function resolveSessionReplyTarget(ds: Pick<DaemonSession, 'scope' | 'chatId' | 'session' | 'currentReplyTarget'>, turnId?: string): SessionReplyTarget;
export declare function resolveSendTarget(opts: {
    into?: string;
    topLevel: boolean;
    chatScope: boolean;
    chatId: string;
    rootMessageId: string;
    replyTargetRootId?: string;
    replyTargetTurnId?: string;
    currentTurnId?: string;
}): SessionReplyTarget;
export declare function beginReplyTargetTurn(ds: DaemonSession, replyRootId: string | undefined, turnId: string, nowIso?: string): void;
/**
 * Effective turnId for a daemon-side message. Callers that know their turn
 * (worker final_output, placeholder cards) pass it explicitly and the
 * stale-turn gate in resolveSessionReplyTarget stays authoritative. Callers
 * with NO turn context of their own (the worker's first streaming card,
 * crash notices) fall back to the session's current reply-target turn — in a
 * shared fold-back topic they then follow the conversation into the thread
 * instead of leaking to the chat top level.
 */
export declare function fallbackTurnId(ds: Pick<DaemonSession, 'session' | 'currentReplyTarget'>, turnId: string | undefined): string | undefined;
export declare function syncReplyTargetState(ds: DaemonSession, s?: Session): void;
//# sourceMappingURL=reply-target.d.ts.map