/**
 * Session Handoff Service
 *
 * Generates a structured session summary on shutdown and pushes it to agents
 * on restart. Replaces the old Slack-only pushRecentSlackHistory approach with
 * a channel-agnostic summary that covers Slack, Google Chat, and Chat UI.
 *
 * Summary is stored at ~/.crewly/session-summaries/latest.md and is limited
 * to 50 lines for prompt-budget friendliness.
 *
 * @module services/session/session-handoff.service
 */
import type { RuntimeType } from '../../constants.js';
/**
 * Information about an active conversation thread.
 */
export interface ActiveThread {
    /** Channel type: 'slack', 'gchat', or 'chat-ui' */
    channelType: 'slack' | 'gchat' | 'chat-ui';
    /** Channel or space identifier */
    channelId: string;
    /** Absolute path to the thread file */
    filePath: string;
    /** ISO timestamp of last modification */
    lastActiveAt: string;
    /** Last few message summaries */
    recentMessages: string[];
}
/**
 * Information about an active team member (agent).
 */
export interface ActiveAgentInfo {
    /** Agent session name */
    sessionName: string;
    /** Agent role */
    role: string;
    /** Current working status */
    workingStatus: string;
    /** Current task description (if any) */
    currentTask?: string;
}
/**
 * Information about a pending (non-completed) task. Sourced from the V3
 * task-pool (`pool.json`) — see {@link SessionHandoffService.scanPendingTasks}.
 *
 * Historically this was scraped from `.crewly/tasks/delegated/*.md`, but
 * that path was retired with the V3↔.md bridge deprecation
 * (`specs/2026-05-06-projecttask-md-deprecation.md`). The shape is preserved
 * for downstream callers; `filePath` now points at the task-pool JSON file
 * (a stable per-process location) rather than a per-task .md file.
 */
export interface PendingTaskInfo {
    /** Task title (WorkItem.title) */
    title: string;
    /** Agent session name the task is assigned to (WorkItem.target) */
    assignedTo: string;
    /** Current WorkItem status — passed through verbatim (e.g. 'queued', 'running') */
    status: string;
    /** Priority if available; empty string when WorkItem doesn't carry one */
    priority: string;
    /** Stable identifier for the task — currently the WorkItem id */
    filePath: string;
}
/**
 * Full session handoff summary data.
 */
export interface HandoffSummary {
    /** ISO timestamp of summary generation */
    generatedAt: string;
    /** Active conversation threads across all channels */
    activeThreads: ActiveThread[];
    /** Active agents and their status */
    activeAgents: ActiveAgentInfo[];
    /** Pending tasks that have not been completed */
    pendingTasks: PendingTaskInfo[];
}
/**
 * Thread info for the resume notification sent after orchestrator restart.
 * Covers Slack, Google Chat, and Chat UI channels.
 */
export interface ResumeThread {
    /** Channel type: 'slack', 'gchat', or 'chat-ui' */
    channelType: 'slack' | 'gchat' | 'chat-ui';
    /** Channel or space identifier */
    channelId: string;
    /** Thread identifier (threadTs for Slack, threadName for GChat, conversationId for Chat UI) */
    threadId: string;
    /** Absolute path to the thread file */
    filePath: string;
    /** ISO timestamp of last modification */
    lastActiveAt: string;
    /** Recent message previews */
    recentMessages: string[];
}
/**
 * @deprecated Use ResumeThread instead. Kept for backward compatibility.
 */
export type SlackResumeThread = ResumeThread;
/**
 * Service to send messages to agents.
 * Minimal interface to avoid tight coupling with AgentRegistrationService.
 */
export interface AgentMessageSender {
    sendMessageToAgent(session: string, content: string, runtimeType: RuntimeType): Promise<{
        success: boolean;
    }>;
}
/**
 * Service to read team data.
 * Minimal interface to avoid tight coupling with StorageService.
 */
export interface TeamDataReader {
    getTeams(): Promise<Array<{
        members: Array<{
            sessionName: string;
            role: string;
            agentStatus: string;
            workingStatus: string;
            currentTickets?: string[];
        }>;
    }>>;
}
/**
 * Manages generation of session summaries on shutdown and delivery on restart.
 *
 * @example
 * ```typescript
 * const handoff = SessionHandoffService.getInstance();
 *
 * // On shutdown:
 * await handoff.generateSummary(storageService);
 *
 * // On agent registration:
 * await handoff.pushSessionSummary(agentService, 'crewly-orc');
 * ```
 */
export declare class SessionHandoffService {
    private static instance;
    private readonly logger;
    private constructor();
    /**
     * Gets the singleton instance.
     *
     * @returns SessionHandoffService instance
     */
    static getInstance(): SessionHandoffService;
    /**
     * Resets the singleton instance (for testing).
     */
    static resetInstance(): void;
    /**
     * Returns the directory path for session summaries.
     *
     * @returns Absolute path to ~/.crewly/session-summaries/
     */
    getSummariesDir(): string;
    /**
     * Returns the path to the latest summary file.
     *
     * @returns Absolute path to ~/.crewly/session-summaries/latest.md
     */
    getLatestSummaryPath(): string;
    /**
     * Scans a thread directory for the most recently modified .md files.
     * Works for both Slack (~/.crewly/slack-threads/) and GChat (~/.crewly/gchat-threads/).
     *
     * @param baseDir - Base directory to scan (e.g., ~/.crewly/slack-threads/)
     * @param channelType - Type of channel ('slack' or 'gchat')
     * @param maxThreads - Maximum number of threads to return
     * @returns Array of ActiveThread info sorted by recency
     */
    scanThreadDirectory(baseDir: string, channelType: 'slack' | 'gchat', maxThreads?: number): Promise<ActiveThread[]>;
    /**
     * Scans Chat UI conversation storage for active conversations.
     *
     * @param chatDir - Path to chat storage directory (default: ~/.crewly/chat/)
     * @param maxConversations - Maximum number of conversations to return
     * @returns Array of ActiveThread info for Chat UI conversations
     */
    scanChatUiConversations(chatDir?: string, maxConversations?: number): Promise<ActiveThread[]>;
    /**
     * Extracts recent message summaries from a markdown thread file.
     * Reads the last few message blocks (lines starting with **Name**).
     *
     * @param filePath - Absolute path to the thread .md file
     * @returns Array of recent message summary strings
     */
    extractRecentMessages(filePath: string): Promise<string[]>;
    /**
     * Extracts recent messages from a Chat UI JSON conversation file.
     *
     * @param filePath - Absolute path to the conversation .json file
     * @returns Array of recent message summary strings
     */
    extractChatUiMessages(filePath: string): Promise<string[]>;
    /**
     * Collects active agent info from team storage.
     *
     * @param teamReader - Service to read team data
     * @returns Array of active agent info
     */
    collectActiveAgents(teamReader: TeamDataReader): Promise<ActiveAgentInfo[]>;
    /**
     * Returns pending (non-terminal) tasks from the V3 task-pool. Replaces the
     * legacy `.crewly/tasks/delegated/{open,in_progress}/*.md` filesystem scan
     * (retired per `specs/2026-05-06-projecttask-md-deprecation.md` —
     * V3 WorkItem is the sole source of truth for delegated work).
     *
     * Selection: any WorkItem in a non-terminal status (`queued`, `scheduled`,
     * `proposed`, `accepted`, `running`, `blocked`, `escalated`,
     * `done_by_worker`, `rejected`) — i.e. anything that still demands
     * attention on a session resume.
     *
     * Sort: running-first (workers actively engaged), then high-priority first.
     *
     * The legacy `tasksBaseDir` parameter is accepted for backwards compat
     * with existing test fixtures but is unused — the source is now the
     * task-pool singleton.
     *
     * @param _tasksBaseDir - Ignored. Kept so callers (e.g. session.controller)
     *                        don't need to be updated in lockstep.
     * @returns Array of PendingTaskInfo sorted, capped at {@link MAX_PENDING_TASKS}
     */
    scanPendingTasks(_tasksBaseDir?: string): Promise<PendingTaskInfo[]>;
    /**
     * Generates a full session handoff summary by scanning all thread stores
     * and collecting active agent status. Saves to ~/.crewly/session-summaries/latest.md.
     *
     * @param teamReader - Service to read team data for agent status
     * @param tasksBaseDir - Override for the tasks base directory (for testing)
     * @returns The generated summary data
     */
    generateSummary(teamReader: TeamDataReader, tasksBaseDir?: string): Promise<HandoffSummary>;
    /**
     * Formats a HandoffSummary into a markdown string, capped at MAX_SUMMARY_LINES.
     *
     * @param summary - The summary data
     * @returns Markdown string
     */
    formatSummaryMarkdown(summary: HandoffSummary): string;
    /**
     * Pushes the latest session summary to an agent after registration.
     * Replaces the old pushRecentSlackHistory function.
     *
     * Reads ~/.crewly/session-summaries/latest.md and sends it as a
     * [SESSION_CONTEXT] system message. Only sends if the summary exists
     * and is non-empty.
     *
     * @param agentService - Service to send messages to agents
     * @param sessionName - Target agent session name
     */
    pushSessionSummary(agentService: AgentMessageSender, sessionName: string): Promise<void>;
    /**
     * Scans a thread directory (Slack or GChat format) for threads modified within maxAge.
     * Filters by file modification time and returns ResumeThread objects.
     *
     * @param baseDir - Directory to scan (e.g., ~/.crewly/slack-threads/)
     * @param channelType - Channel type ('slack' or 'gchat')
     * @param cutoffMs - Cutoff timestamp in ms (threads older than this are excluded)
     * @returns Array of ResumeThread for qualifying threads
     */
    private scanRecentMdThreads;
    /**
     * Scans Chat UI conversations for those modified within maxAge.
     *
     * @param chatDir - Chat UI directory path
     * @param cutoffMs - Cutoff timestamp in ms
     * @returns Array of ResumeThread for qualifying conversations
     */
    private scanRecentChatUiThreads;
    /**
     * Finds threads across all chat channels (Slack, GChat, Chat UI) that were
     * active within the specified time window.
     *
     * @param maxAge - Maximum age in ms for a thread to qualify (default: 24h)
     * @param dirOverrides - Optional directory overrides for testing
     * @returns Array of ResumeThread sorted by most recent first
     */
    findRecentThreads(maxAge?: number, dirOverrides?: {
        slackDir?: string;
        gchatDir?: string;
        chatDir?: string;
    }): Promise<ResumeThread[]>;
    /**
     * @deprecated Use findRecentThreads() instead. Kept for backward compatibility.
     * Finds Slack threads that were active within the last 24 hours.
     *
     * @param maxAge - Maximum age in ms for a thread to qualify (default: 24h)
     * @param slackDirOverride - Optional directory override (for testing)
     * @returns Array of ResumeThread sorted by most recent first (Slack only)
     */
    findRecentSlackThreads(maxAge?: number, slackDirOverride?: string): Promise<ResumeThread[]>;
    /**
     * Pushes a [CHAT_RESUME] notification to the orchestrator after registration,
     * containing info about recently active threads across all channels (Slack,
     * GChat, Chat UI) so it can proactively send a greeting message.
     *
     * @param agentService - Service to send messages to agents
     * @param sessionName - Target agent session name (typically the orchestrator)
     */
    pushResumeNotification(agentService: AgentMessageSender, sessionName: string): Promise<void>;
    /**
     * @deprecated Use pushResumeNotification() instead.
     */
    pushSlackResumeNotification(agentService: AgentMessageSender, sessionName: string): Promise<void>;
}
//# sourceMappingURL=session-handoff.service.d.ts.map