import { Connection, SfProject } from '@salesforce/core';
import { type PlannerResponse, PreviewMetadata } from './types';
export declare const metric: readonly ["completeness", "coherence", "conciseness", "output_latency_milliseconds"];
/**
 * Sanitize a filename by removing or replacing illegal characters.
 * This ensures the filename is valid across different operating systems.
 *
 * @param filename - The filename to sanitize
 * @returns A sanitized filename safe for use across operating systems
 */
export declare const sanitizeFilename: (filename: string) => string;
/**
 * Clean a string by replacing HTML entities with their respective characters.
 *
 * @param str - The string to clean.
 * @returns The cleaned string with all HTML entities replaced with their respective characters.
 */
export declare const decodeHtmlEntities: (str?: string) => string;
/**
 * Find the authoring bundle directory for a given bot name by recursively searching from a starting directory or directories.
 *
 * @param dirOrDirs - The directory or array of directories to start searching from
 * @param botName - The name of the bot to find the authoring bundle directory for
 * @returns The path to the authoring bundle directory if found, undefined otherwise
 */
export declare const findAuthoringBundle: (dirOrDirs: string | string[], botName: string) => string | undefined;
/**
 * Find all local agent files matching the pattern aiAuthoringBundles/<name>/<name>.agent
 * Only descends into aiAuthoringBundles to check direct children (no full tree walk under it).
 *
 * @param dir - The directory to start searching from
 * @returns Array of paths to agent files
 */
export declare const findLocalAgents: (dir: string) => string[];
/**
 * takes a connection and upgrades it to a NamedJWT connection
 *
 * @param {Connection} connection original Connection
 * @returns {Promise<Connection>} upgraded connection
 */
export declare const useNamedUserJwt: (connection: Connection) => Promise<Connection>;
export type TranscriptRole = 'user' | 'agent';
export type TranscriptEntry = {
    timestamp: string;
    agentId: string;
    sessionId: string;
    role: TranscriptRole;
    text?: string;
    reason?: string;
    raw?: any;
};
export type TurnIndexEntry = {
    turn: number;
    timestamp: string;
    role: TranscriptRole;
    summary: string;
    summaryTruncated: boolean;
    multiModal: string | null;
    traceFile: string | null;
    planId: string | null;
    reason?: string;
};
export type TurnIndex = {
    version: string;
    sessionId: string;
    agentId: string;
    created: string;
    turns: TurnIndexEntry[];
};
/**
 * returns a path, and ensures it's created, to the agents history directory
 *
 * Initialize session directory
 * Session directory structure:
 * .sfdx/agents/<agentId>/sessions/<sessionId>/
 * ├── transcript.jsonl    # All transcript entries (one per line)
 * ├── turn-index.json     # Turn-trace correlation index
 * ├── traces/             # Individual trace files
 * │   ├── <planId1>.json
 * │   └── <planId2>.json
 * └── metadata.json       # Session metadata (start time, end time, planIds, etc.)
 *
 * @param {string} agentId gotten from Agent.getAgentIdForStorage()
 * @param {string} sessionId the preview's start call .SessionId
 * @returns {Promise<string>} path to where history/metadata/transcripts are stored inside of local .sfdx
 */
export declare const getHistoryDir: (agentId: string, sessionId: string) => Promise<string>;
/**
 * Get the path to the agent index directory.  Create the directory if it doesn't exist.
 *
 * .sfdx/agents/<agentId>/   <-- returns this directory path
 * ├── index.md            # Session index file
 * │── sessions/           # Session directories
 * │   ├── <sessionId1>/   # Session 1 directory
 * │   └── <sessionId2>/   # Session 2 directory
 *
 * @param {string} agentId
 * @returns {Promise<string>} path to the agent index directory
 */
export declare const getAgentIndexDir: (agentId: string) => Promise<string>;
/**
 * Append a transcript entry to the transcript.jsonl transcript file
 *
 * @param {TranscriptEntry} entry to save
 * @param {string} sessionDir the preview's start call .SessionId
 * @returns {Promise<void>}
 */
export declare const appendTranscriptToHistory: (entry: TranscriptEntry, sessionDir: string) => Promise<void>;
/**
 * writes a trace to <plan-id>.json in history directory
 *
 * @param {string} planId
 * @param {PlannerResponse | undefined} trace
 * @param {string} historyDir
 * @returns {Promise<void>}
 */
export declare const writeTraceToHistory: (planId: string, trace: PlannerResponse | undefined, historyDir: string) => Promise<void>;
export type TraceFileInfo = {
    planId: string;
    path: string;
    size: number;
    mtime: Date;
};
/**
 * List trace files for a given agent session.
 *
 * Returns one entry per .json file in the session's traces/ directory.
 * File path is absolute. Returns an empty array if the traces directory does not exist.
 */
export declare const listSessionTraces: (agentId: string, sessionId: string) => Promise<TraceFileInfo[]>;
/**
 * Read a single trace file by planId. Returns null if the file does not exist or cannot be parsed.
 */
export declare const readSessionTrace: (agentId: string, sessionId: string, planId: string) => Promise<PlannerResponse | null>;
/**
 * Read the turn-index.json for a session. Returns null if not found.
 */
export declare const readTurnIndex: (agentId: string, sessionId: string) => Promise<TurnIndex | null>;
/**
 * Write or append a session line to .sfdx/agents/<agentId>/index.md.
 * If the file does not exist, creates it with a header and the session line.
 * If it exists, appends the new session line.
 */
export declare const logSessionToIndex: (agentDir: string, options: {
    sessionId: string;
    startTime: string;
    simulated: boolean;
    agentId: string;
}) => Promise<void>;
/**
 * In-memory buffer for session history to minimize file I/O during conversation
 */
export declare class SessionHistoryBuffer {
    private readonly sessionDir;
    private readonly sessionId;
    private readonly agentId;
    private readonly created;
    private readonly mockMode?;
    private turnEntries;
    private planIds;
    constructor(sessionDir: string, sessionId: string, agentId: string, created: string, mockMode?: "Mock" | "Live Test" | undefined);
    /**
     * Create a SessionHistoryBuffer from existing session data on disk
     * Used when resuming an existing session
     */
    static fromDisk(sessionDir: string, sessionId: string, agentId: string): Promise<{
        buffer: SessionHistoryBuffer;
        turnCount: number;
    }>;
    /**
     * Add a turn to the buffer (no file I/O)
     */
    addTurn(entry: TurnIndexEntry): void;
    /**
     * Add a planId to the buffer (no file I/O)
     */
    addPlanId(planId: string): void;
    /**
     * Update an existing turn with trace info (no file I/O)
     */
    updateTurnWithTrace(turnNumber: number, planId: string): void;
    /**
     * Flush all buffered data to disk
     * Called at session start (to create initial files), after each turn (to keep real-time), and at session end (to finalize)
     */
    flush(endTime?: string): Promise<void>;
}
/**
 * Log a turn to history using buffer (fast, no read-modify-write)
 *
 * @param {TranscriptEntry} entry the transcript entry to log
 * @param {number} turnNumber the turn number (1-based)
 * @param {string} sessionDir path to the session directory
 * @param {SessionHistoryBuffer} buffer buffer for batched writes
 * @returns {Promise<void>}
 */
export declare const logTurnToHistory: (entry: TranscriptEntry, turnNumber: number, sessionDir: string, buffer: SessionHistoryBuffer) => Promise<void>;
/**
 * Extract HTTP status code from API errors. Supports:
 * - ERROR_HTTP_404 / ERROR_HTTP_500 style (name, errorCode, or data.errorCode)
 * - Numeric statusCode on error, cause, or response
 */
export declare function getHttpStatusCode(err: unknown): number | undefined;
export type RequestInfo = {
    url: string;
    method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD';
    headers?: Record<string, string>;
    body?: string;
};
/**
 * Makes an API request with automatic endpoint fallback.
 * Tries api.salesforce.com first, then test.api.salesforce.com on 404, then dev.api.salesforce.com on 404.
 *
 * @param connection - The Salesforce connection
 * @param requestInfo - The request information (url, method, headers, body, etc.)
 * @param options - Optional retry/timeout options
 * @returns The API response
 * @throws SfError if all endpoints return 404, or immediately on non-404 errors
 */
export declare function requestWithEndpointFallback<T>(connection: Connection, requestInfo: RequestInfo, options?: {
    retry?: {
        maxRetries?: number;
    };
}): Promise<T>;
/**
 * Record a trace for a turn using buffer (fast, minimal I/O)
 *
 * @param {string} historyDir path to the session directory
 * @param {number} turnNumber the turn number that generated this trace
 * @param {string} planId the plan ID for this trace
 * @param {PlannerResponse | undefined} trace the trace data to write
 * @param {SessionHistoryBuffer} buffer buffer for batched updates
 * @returns {Promise<void>}
 */
export declare const recordTraceForTurn: (historyDir: string, turnNumber: number, planId: string, trace: PlannerResponse | undefined, buffer: SessionHistoryBuffer) => Promise<void>;
/**
 * Get all history data for a session including metadata, transcript, and traces
 *
 * @param agentId gotten from Agent.getAgentIdForStorage()
 * @param sessionId optional - the preview sessions' ID, gotten originally from /start .SessionId. If not provided, returns the most recent conversation
 * @returns Object containing parsed metadata, transcript entries, and traces
 */
export declare const getAllHistory: (agentId: string, sessionId: string | undefined) => Promise<{
    metadata: PreviewMetadata | null;
    transcript: TranscriptEntry[];
    traces: PlannerResponse[];
}>;
/**
 * Read and parse the last conversation's transcript entries from JSON.
 *
 * @param agentId gotten from Agent.getAgentIdForStorage()
 * @param sessionId the preview sessions' ID, gotten originally from /start .SessionId
 * @returns Array of TranscriptEntry in file order (chronological append order).
 */
export declare const readTranscriptEntries: (agentId: string, sessionId: string) => Promise<TranscriptEntry[]>;
export type TestRunnerType = 'agentforce-studio' | 'testing-center';
/** Detects the test runner from a run ID's Salesforce ID prefix (`3A2` = Agentforce Studio, `4KB` = Testing Center). */
export declare function detectTestRunnerFromId(runId: string): TestRunnerType | undefined;
/**
 * Determines which test runner to use based on available metadata types in the org.
 *
 * This function checks for the presence of:
 * - `AiEvaluationDefinition` (Testing Center)
 * - `AiTestingDefinition` (Agentforce Studio)
 *
 * If a test definition with the same name exists in both metadata types, an error is thrown
 * to prevent ambiguity.
 *
 * @param connection - The Salesforce connection
 * @param testDefinitionName - Optional test definition name to check for conflicts
 * @returns 'agentforce-studio' if only Agentforce Studio metadata exists, 'testing-center' if only Testing Center metadata exists
 * @throws {SfError} if both metadata types exist with the same test definition name
 * @throws {SfError} if neither metadata type exists
 *
 * @example
 * ```typescript
 * const runnerType = await determineTestRunner(connection, 'MyTestSuite');
 * if (runnerType === 'agentforce-studio') {
 *   const tester = new AgentforceStudioTester(connection);
 * } else {
 *   const tester = new AgentTester(connection);
 * }
 * ```
 */
export declare function determineTestRunner(connection: Connection, testDefinitionName?: string): Promise<TestRunnerType>;
export type SessionType = 'simulated' | 'live' | 'published';
export type PreviewSessionMeta = {
    displayName?: string;
    timestamp?: string;
    sessionType?: SessionType;
};
/**
 * Save a marker so send/end can validate that the session was started for this agent.
 * Caller must have started the session (agent has sessionId set). Uses agent.getHistoryDir() for the path.
 * Pass displayName (authoring bundle name or production agent API name) so "agent preview sessions" can show it.
 */
export declare function createPreviewSessionCache(agent: {
    getHistoryDir: () => Promise<string>;
}, options?: {
    displayName?: string;
    sessionType?: SessionType;
}): Promise<void>;
/**
 * Validate that the session was started for this agent (marker file exists in agent's history dir for current sessionId).
 * Caller must set sessionId on the agent (agent.setSessionId) before calling.
 * Throws SfError if the session marker is not found.
 */
export declare function validatePreviewSession(agent: {
    getHistoryDir: () => Promise<string>;
}): Promise<void>;
/**
 * Remove the session marker so this session is no longer considered "active" for send/end without --session-id.
 * Call after ending the session. Caller must set sessionId on the agent before calling.
 */
export declare function removePreviewSessionCache(agent: {
    getHistoryDir: () => Promise<string>;
}): Promise<void>;
/**
 * List session IDs that have a cache marker (started via "agent preview start") for this agent.
 * Uses project path and agent's storage ID to find .sfdx/agents/<agentId>/sessions/<sessionId>/session-meta.json.
 */
export declare function getCachedPreviewSessionIds(project: SfProject, agent: {
    getAgentIdForStorage: () => string | Promise<string>;
}): Promise<string[]>;
/**
 * Return the single "current" session ID when safe: exactly one cached session for this agent.
 * Returns undefined when there are zero or multiple sessions (caller should require --session-id).
 */
export declare function getCurrentPreviewSessionId(project: SfProject, agent: {
    getAgentIdForStorage: () => string | Promise<string>;
}): Promise<string | undefined>;
export type CachedPreviewSessionInfo = {
    sessionId: string;
    timestamp?: string;
    sessionType?: SessionType;
};
export type CachedPreviewSessionEntry = {
    agentId: string;
    displayName?: string;
    sessions: CachedPreviewSessionInfo[];
};
/**
 * List all cached preview sessions in the project, grouped by agent ID.
 * displayName (when present in session-meta.json) is the authoring bundle name or production agent API name for display.
 * Use this to show users which sessions exist so they can end or clean up.
 */
export declare function listCachedPreviewSessions(project: SfProject): Promise<CachedPreviewSessionEntry[]>;
