export function resolveSessionReplyTarget(ds, turnId) {
    const target = ds.currentReplyTarget ?? ds.session.currentReplyTarget;
    if (ds.scope === 'chat') {
        if (target?.rootMessageId && !!turnId && target.turnId === turnId) {
            return { mode: 'thread', rootMessageId: target.rootMessageId };
        }
        return { mode: 'plain', chatId: ds.chatId };
    }
    return { mode: 'thread', rootMessageId: ds.session.rootMessageId };
}
export function resolveSendTarget(opts) {
    if (opts.into)
        return { mode: 'thread', rootMessageId: opts.into };
    if (opts.topLevel)
        return { mode: 'plain', chatId: opts.chatId };
    if (opts.chatScope) {
        return opts.replyTargetRootId && opts.replyTargetTurnId && opts.replyTargetTurnId === opts.currentTurnId
            ? { mode: 'thread', rootMessageId: opts.replyTargetRootId }
            : { mode: 'plain', chatId: opts.chatId };
    }
    return { mode: 'thread', rootMessageId: opts.rootMessageId };
}
export function beginReplyTargetTurn(ds, replyRootId, turnId, nowIso = new Date().toISOString()) {
    if (ds.scope !== 'chat')
        return;
    if (replyRootId) {
        const aliases = { ...(ds.replyThreadAliases ?? ds.session.replyThreadAliases ?? {}) };
        aliases[replyRootId] = {
            createdAt: aliases[replyRootId]?.createdAt ?? nowIso,
            lastUsedAt: nowIso,
        };
        const target = { rootMessageId: replyRootId, turnId, updatedAt: nowIso };
        ds.replyThreadAliases = aliases;
        ds.currentReplyTarget = target;
        ds.session.replyThreadAliases = aliases;
        ds.session.currentReplyTarget = target;
        return;
    }
    ds.currentReplyTarget = undefined;
    ds.session.currentReplyTarget = undefined;
}
/**
 * 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 function fallbackTurnId(ds, turnId) {
    return turnId ?? (ds.currentReplyTarget ?? ds.session.currentReplyTarget)?.turnId;
}
export function syncReplyTargetState(ds, s) {
    const source = s ?? ds.session;
    ds.replyThreadAliases = source.replyThreadAliases;
    ds.currentReplyTarget = source.currentReplyTarget;
}
//# sourceMappingURL=reply-target.js.map