import { sessionTerminalHref } from './session-terminal.js'; export declare function tokenCount(value: unknown): number | null; export declare function formatTokenCount(value: unknown): string; export interface SessionExchangePreview { userText: string; userFullText: string; botText: string; botFullText: string; } /** Latest user/bot exchange for a session card. A bot preview is shown only * when it is newer than the latest user input; otherwise the card communicates * the still-waiting state with the user line alone. */ export declare function sessionExchangePreview(row: Record): SessionExchangePreview; /** Reducer backing the session-card preview overlay's open/focus state. The * component drives its `useReducer` with these exact actions (not a parallel * mirror), so this unit-tests the real transitions — in particular the * Escape→refocus race: Escape closes the overlay AND returns focus to the * trigger, whose `focus` action would otherwise reopen it in the same event, so * `escape-refocus` arms a one-shot `suppressFocusOpen` that the immediately * following `focus` consumes instead of opening. */ export interface PreviewOverlayState { open: boolean; /** One-shot: the next trigger `focus` must NOT open (set by escape-refocus). */ suppressFocusOpen: boolean; } export type PreviewOverlayAction = 'open' | 'close' | 'focus' | 'escape-refocus' | 'toggle'; export declare const previewOverlayInitialState: PreviewOverlayState; export declare function previewOverlayReducer(state: PreviewOverlayState, action: PreviewOverlayAction): PreviewOverlayState; export declare const CLI_FILTER_OPTIONS: string[]; export type BoardColumnId = 'needs-you' | 'working' | 'todo' | 'idle'; export declare const BOARD_COLUMNS: Array<{ id: BoardColumnId; labelKey: string; hintKey: string; }>; export declare function cssToken(value: unknown): string; export declare const SESSION_STATUS_OPTIONS: string[]; export declare function sessionStatusText(status: unknown): string; export declare function sessionRuntimeCounts(rows: Iterable): { logical: number; resident: number; dormant: number; }; export declare function repoBasename(workingDir: unknown): string; /** 单聊(p2p)会话的展示名:`单聊 · 用户名 - bot名`。 * 用户名取 chatDisplayName(缺失回退 chatId);bot 名取 botDisplayName * (与表格 bot 列同源)。群聊/未知聊天不走这里。 */ export declare function sessionDirectChatText(s: any): string; export declare function sessionLocationText(s: any): string; export declare function isUnknownChatSession(s: any, resolveTitle?: (session: any) => string | null): boolean; /** True when a chat-filter label still falls back to the raw `chatId` (no * human-readable name resolved). Used to demote unresolved labels during * option dedup so a named session always wins over an id-only one. */ export declare function chatFilterLabelIsUnresolved(label: string, chatId: string): boolean; /** Pick the better of two chat-filter labels for the same `chatId`. A label * that resolved to a real name beats one that still shows the raw id; when both * are equally (un)resolved, fall back to a deterministic lexicographic pick so * option ordering stays stable across renders. * * Fixes the dedup bug where `label < existing` alone let a raw-id label * (ASCII `oc_…`, which sorts before CJK names) mask an already-resolved name * such as `单聊 · 韩毅 - Nil-RD`. */ export declare function preferChatFilterLabel(existing: string | undefined, candidate: string, chatId: string): string; export declare function sessionLocationTitle(s: any): string; export declare function sessionSearchText(s: any): string; export type SessionTopicKind = 'thread' | 'chat' | 'session'; /** Location-level grouping used by the Dashboard topic view. * * This is intentionally not called a collaboration graph. A thread anchor * proves that sessions live in the same Lark topic, while chat-scope sessions * can only be grouped at whole-chat granularity. Neither relation proves which * session woke another one. */ export interface SessionTopicGroup { key: string; kind: SessionTopicKind; chatId: string; rootMessageId?: string; title: string; rows: T[]; botCount: number; activeCount: number; closedCount: number; inferredBotInputCount: number; latestActivityAt: number; multiBot: boolean; inferredBotTriggered: boolean; } /** Stable location key for the current schema. Keep it separate from any * future `collaborationId`: location and logical task identity are different * dimensions and must not silently alias each other. */ export declare function sessionTopicKey(s: any): string; /** Group arbitrary Dashboard rows by their best available Lark conversation * anchor. Groups and members are sorted by recent activity for deterministic * rendering. */ export declare function groupSessionsByTopic>(rows: readonly T[]): SessionTopicGroup[]; export declare const terminalHref: typeof sessionTerminalHref; export declare function shouldOpenWritableTerminal(state?: { authed: boolean; publicReadOnly: boolean; }): boolean; export declare const ICON: { pin: string; openChat: string; details: string; terminal: string; key: string; lock: string; unlock: string; close: string; edit: string; history: string; restart: string; feishu: string; copy: string; }; export declare function lockActionLabel(s: any): string; export declare function openWriteLink(s: any, btn?: HTMLButtonElement): Promise; export declare function copySpawnCommand(s: any, btn?: HTMLButtonElement): Promise; export declare function historySenderKey(message: any): string; export declare function deriveSessionBoardColumn(s: any): BoardColumnId | null; /** 会话是否有未完成 TODO(任务态)。openTodos 缺失 = 未知/不支持 → 视为无。 */ export declare function hasOpenTodos(s: any): boolean; export declare function restartConfirmMessage(s: any): string; export declare function canRestartSession(s: any): boolean; export interface PickerBot { larkAppId: string; botName: string; } export declare function fetchPickerBots(): Promise; //# sourceMappingURL=sessions.d.ts.map