/**
 * @fileoverview Shared data layer for the Realtime Voice analytics sections.
 *
 * Loads `MJ: AI Agent Sessions`, their `MJ: AI Agent Session Channels` rows,
 * and the delegated `MJ: AI Agent Runs` (linked via `AgentSessionID`) in a
 * single batched `RunViews` call, then aggregates everything client-side into
 * per-session rollups (target agent, channel set, delegated-run count, token /
 * cost totals, duration, close cause from the persisted `CloseReason` column).
 *
 * Used by both `AnalyticsRealtimeOverviewComponent` (KPIs + charts) and
 * `AnalyticsRealtimeSessionsComponent` (management grid) so the two sections
 * share one query shape and one aggregation pass.
 */
import { IMetadataProvider } from '@memberjunction/core';
/**
 * Why a session was closed, as stamped server-side by `SessionManager.CloseSession`
 * (mirrors `AIAgentSessionEntity.CloseReason`). `null` means a legacy row closed
 * before the column existed — rendered as "unknown".
 */
export type RealtimeSessionCloseReason = 'Error' | 'Explicit' | 'Janitor' | 'Shutdown';
export interface RealtimeSessionRecord {
    ID: string;
    AgentID: string;
    Agent: string | null;
    UserID: string;
    User: string;
    Status: 'Active' | 'Idle' | 'Closed';
    ConversationID: string | null;
    LastSessionID: string | null;
    HostInstanceID: string | null;
    Config: string | null;
    LastActiveAt: string;
    ClosedAt: string | null;
    CloseReason: RealtimeSessionCloseReason | null;
    __mj_CreatedAt: string;
}
export interface RealtimeSessionChannelRecord {
    ID: string;
    AgentSessionID: string;
    Channel: string;
    Status: string;
    __mj_CreatedAt: string;
}
export interface RealtimeSessionRunRecord {
    ID: string;
    AgentSessionID: string | null;
    AgentID: string;
    Agent: string | null;
    TotalCost: number | null;
    TotalTokensUsed: number | null;
    StartedAt: string;
}
/** One session with everything the admin pages render, pre-aggregated. */
export interface RealtimeSessionRollup {
    Record: RealtimeSessionRecord;
    /** Parsed from Config JSON; null when the session carries no target. */
    TargetAgentID: string | null;
    /** Resolved client-side against AIEngineBase's cached agents. */
    TargetAgentName: string | null;
    /** Distinct channel names attached to the session. */
    ChannelNames: string[];
    /** Delegated AIAgentRuns (linked runs excluding the co-agent observability run). */
    DelegatedRunCount: number;
    /** Token total across all linked agent runs (co-agent + delegated). */
    TotalTokens: number;
    /** Cost total across all linked agent runs (co-agent + delegated). */
    TotalCost: number;
    StartedAt: Date;
    /** __mj_CreatedAt → (ClosedAt ?? LastActiveAt). 0 when not derivable. */
    DurationMs: number;
    /** Session resumed from a prior one (LastSessionID set). */
    IsResumed: boolean;
    /**
     * Close cause persisted by the server (`AIAgentSession.CloseReason`).
     * `null` either means the session is still open, or it's a legacy row
     * closed before the column existed ("unknown" in the UI).
     */
    CloseReason: RealtimeSessionCloseReason | null;
    /**
     * `CloseReason === 'Janitor'` — the session was force-closed by the
     * lifecycle janitor (startup orphan recovery or staleness sweep) rather
     * than ended explicitly. Derived from the real column; the old
     * ClosedAt−LastActiveAt timing heuristic has been retired, so legacy
     * NULL-reason rows report `false` here and "unknown" in the UI.
     */
    IsJanitorClosed: boolean;
}
/** Result of one load pass — current-window rollups plus trend context. */
export interface RealtimeSessionsDataset {
    /** Sessions started in the current window (or still open), newest first. */
    Sessions: RealtimeSessionRollup[];
    /** Every loaded session rollup (covers 2× the window, for trend math). */
    AllSessions: RealtimeSessionRollup[];
    /** Count of sessions started in the prior (equal-length) window. */
    PriorWindowSessionCount: number;
    WindowStart: Date;
    WindowMs: number;
}
export declare function TimeRangeToMs(range: string): number;
/**
 * Loads sessions (2× window for trend), their channels, and linked agent runs
 * via one batched RunViews call, then folds them into per-session rollups.
 */
export declare function LoadRealtimeSessionsDataset(provider: IMetadataProvider, timeRange: string): Promise<RealtimeSessionsDataset>;
/** How a session's status pill should render — label, hover title, and Font Awesome icon. */
export interface SessionStatusDisplay {
    Label: string;
    Title: string;
    /** Icon class for the pill; empty for `Active` (the template renders the pulsing live dot instead). */
    Icon: string;
}
/**
 * Builds the status-pill presentation for a session from its `Status` and persisted
 * `CloseReason`. `Closed` sessions surface the real close cause; a `null` reason
 * (legacy rows written before the column existed) renders as "unknown".
 */
export declare function BuildSessionStatusDisplay(status: RealtimeSessionRecord['Status'], closeReason: RealtimeSessionCloseReason | null): SessionStatusDisplay;
/** Formats a duration as m:ss (or h:mm:ss past the hour) like the mockups' 4:51 / 11:18. */
export declare function FormatSessionDuration(ms: number): string;
/** 4200 → "4.2K", 1_250_000 → "1.3M". */
export declare function FormatTokenCount(value: number): string;
export declare function FormatSessionCost(value: number, decimals?: number): string;
/** Today → "3:40 pm", yesterday → "Yesterday", else "M/d". */
export declare function FormatSessionStart(date: Date): string;
/** Font Awesome icon for a channel name (keyword-mapped, with a generic fallback). */
export declare function ChannelIconClass(channelName: string): string;
//# sourceMappingURL=realtime-session-data.d.ts.map