import type { DaemonSession } from './types.js';
import type { Session, StreamStatus } from '../types.js';
import type { CliId } from '../adapters/cli/types.js';
import { type Brand } from '../im/lark/lark-hosts.js';
import { type SessionTokenUsage } from './cost-calculator.js';
export interface SessionRow {
    sessionId: string;
    larkAppId: string;
    botName: string;
    cliId: CliId | 'unknown';
    status: StreamStatus | 'closed';
    adopt: boolean;
    spawnedAt: number;
    lastMessageAt: number;
    closedAt?: number;
    workingDir?: string;
    chatId: string;
    rootMessageId: string;
    threadId?: string;
    /** Conversation unit ('thread' = topic-anchored, 'chat' = plain chat scope).
     *  Drives the board's locate button: chat-scope sessions have no topic to
     *  locate, so the dashboard offers "open chat" (feishuChatLink) instead.
     *  Absent on rows from older daemons → callers keep the locate behavior. */
    scope?: 'thread' | 'chat';
    title?: string;
    /** 看板视图的手动放置（列 id / 列内排序位置），用户拖拽后持久化在 Session 上。
     *  未设置时前端按运行状态推导默认列。 */
    kanbanColumn?: string;
    kanbanPosition?: number;
    ownerOpenId?: string;
    webPort: number | null;
    /** Owning daemon's advertised reverse-proxy port — WEB_EXTERNAL_PORT + botIndex
     *  when configured, else the bound proxy port (0/undefined if the proxy isn't
     *  up). When set, the terminal is reachable at {host}:{proxyPort}/s/{sessionId}.
     *  Mirrors the port buildTerminalUrl puts in card links so both agree. */
    proxyPort?: number;
    cliVersion?: string;
    hasHistory?: boolean;
    feishuChatLink: string;
    /** Repo-selection card is waiting for a click — the CLI has not spawned yet.
     *  Feeds the board view's needs-you column. */
    pendingRepo?: boolean;
    /** A TUI prompt card is open and waiting for the user's choice.
     *  Feeds the board view's needs-you column. */
    tuiPromptActive?: boolean;
    /** The agent raised a hand (`botmux send --attention`) — it hit a blocker
     *  needing human intervention. Carries the human-readable reason so the
     *  board/overview can show *why* at a glance, plus `at` (epoch ms when it
     *  was raised) so the UI shows a true "waiting since" time — NOT lastMessageAt,
     *  which a silent raise never bumps. Feeds the needs-you column. */
    agentAttention?: {
        kind: string;
        reason: string;
        at: number;
    };
    /** Native Agent CLI token usage for this session. Null means unavailable. */
    tokenUsage?: SessionTokenUsage | null;
}
export declare function feishuChatLink(chatId: string, brand?: Brand): string;
export declare function setBotName(name: string): void;
export declare function getBotName(): string;
export declare function sessionLastActivityAtMs(s: Session): number;
export declare function composeRowFromActive(ds: DaemonSession): SessionRow;
export declare function composeRowFromClosed(s: Session): SessionRow;
//# sourceMappingURL=dashboard-rows.d.ts.map