/**
 * AgentSession - Core abstraction for agent lifecycle and session management.
 *
 * This class is shared between all run modes (interactive, print, rpc).
 * It encapsulates:
 * - Agent state access
 * - Event subscription with automatic session persistence
 * - Model and thinking level management
 * - Compaction (manual and auto)
 * - Bash execution
 * - Session switching and branching
 *
 * Modes use this class and add their own I/O layer on top.
 */
import { type Agent, type AgentEvent, type AgentMessage, type AgentState, type AgentTool, type StreamFn, type ThinkingLevel } from "@earendil-works/pi-agent-core";
import type { ImageContent, Model, TextContent } from "@earendil-works/pi-ai/compat";
import { type BashResult } from "./bash-executor.ts";
import type { CacheWarmer, CacheWarmingStatus } from "./cache-warmer.ts";
import { type CompactionResult } from "./compaction/index.ts";
import { type ContextUsage, type ExtensionCommandContextActions, type ExtensionErrorListener, type ExtensionMode, ExtensionRunner, type ExtensionUIContext, type InputSource, type ReplacedSessionContext, type SessionStartEvent, type ShutdownHandler, type ToolDefinition, type ToolInfo } from "./extensions/index.ts";
import { type CustomMessage } from "./messages.ts";
import type { ModelRuntime } from "./model-runtime.ts";
import { type PromptTemplate } from "./prompt-templates.ts";
import type { ResourceLoader } from "./resource-loader.ts";
import { type BranchSummaryEntry, type SessionEntry, SessionManager } from "./session-manager.ts";
import { type CacheWarmingMode, type SettingsManager } from "./settings-manager.ts";
import { type BashOperations } from "./tools/bash.ts";
/** Mark `streamFn` as resolving auth through `modelRuntime` on its own. */
export declare function markRuntimeStreamFunction(streamFn: StreamFn, modelRuntime: ModelRuntime): void;
/** Parsed skill block from a user message */
export interface ParsedSkillBlock {
    name: string;
    location: string;
    content: string;
    userMessage: string | undefined;
}
/**
 * Parse a skill block from message text.
 * Returns null if the text doesn't contain a skill block.
 */
export declare function parseSkillBlock(text: string): ParsedSkillBlock | null;
/** Tool execution events of calls a tool made through `ctx.executeTool()` carry `parentToolCallId`. */
type WithParentToolCallId<E> = E extends {
    type: "tool_execution_start" | "tool_execution_update" | "tool_execution_end";
} ? E & {
    parentToolCallId?: string;
} : E;
/** Session-specific events that extend the core AgentEvent */
export type AgentSessionEvent = WithParentToolCallId<Exclude<AgentEvent, {
    type: "agent_end";
}>> | {
    type: "agent_end";
    messages: AgentMessage[];
    willRetry: boolean;
} | {
    type: "agent_settled";
    aborted: boolean;
} | {
    type: "queue_update";
    steering: readonly string[];
    followUp: readonly string[];
} | {
    type: "compaction_start";
    reason: "manual" | "threshold" | "overflow";
} | {
    type: "entry_appended";
    entry: SessionEntry;
} | {
    type: "session_info_changed";
    name: string | undefined;
} | {
    type: "thinking_level_changed";
    level: ThinkingLevel;
} | {
    type: "compaction_end";
    reason: "manual" | "threshold" | "overflow";
    result: CompactionResult | undefined;
    aborted: boolean;
    willRetry: boolean;
    errorMessage?: string;
} | {
    type: "auto_retry_start";
    attempt: number;
    maxAttempts: number;
    delayMs: number;
    errorMessage: string;
} | {
    type: "auto_retry_end";
    success: boolean;
    attempt: number;
    finalError?: string;
} | {
    type: "summarization_retry_scheduled";
    attempt: number;
    maxAttempts: number;
    delayMs: number;
    errorMessage: string;
} | {
    type: "summarization_retry_attempt_start";
    source: "branchSummary";
} | {
    type: "summarization_retry_attempt_start";
    source: "compaction";
    reason: "manual" | "threshold" | "overflow";
} | {
    type: "summarization_retry_finished";
} | {
    type: "bash_execution_update";
    id?: string;
    delta: string;
};
/** Listener function for agent session events */
export type AgentSessionEventListener = (event: AgentSessionEvent) => void;
export interface AgentSessionConfig {
    agent: Agent;
    sessionManager: SessionManager;
    settingsManager: SettingsManager;
    cwd: string;
    /** Models to cycle through with Ctrl+P (from --models flag) */
    scopedModels?: Array<{
        model: Model<any>;
        thinkingLevel?: ThinkingLevel;
    }>;
    /** Resource loader for extensions, skills, prompts, themes, context files, and system prompt */
    resourceLoader: ResourceLoader;
    /** SDK custom tools registered outside extensions */
    customTools?: ToolDefinition[];
    /** Canonical model/auth runtime used by coding-agent internals. */
    modelRuntime: ModelRuntime;
    /** Keeps the prompt cache entry of the last session request warm. */
    cacheWarmer?: Pick<CacheWarmer, "cancel" | "status" | "onAgentSettled" | "onModeChanged" | "onWarmed">;
    /** Initial active built-in tool names. Default: [read, bash, edit, write] */
    initialActiveToolNames?: string[];
    /**
     * Whether the initial tools come from the `defaultTools` setting. When true, a resumed session
     * replaces them with the loadout its transcript records, with `defaultToolModifiers` applied, and
     * reload activates tools newly added to the setting. Tools removed from it stay active.
     */
    usesDefaultTools?: boolean;
    /**
     * `+name`/`-name` entries applied on top of the `defaultTools` setting, from `--tools`. Reload
     * applies them to the reloaded setting too, so a removed tool stays removed.
     */
    defaultToolModifiers?: string[];
    /**
     * Optional allowlist of tool names or patterns (`*` matches any characters). When provided, only
     * matching tools are exposed. A non-empty list without `mcp__` entries also keeps MCP tools
     * registered for codemode and tool_search; only tool_search can declare them. An empty list
     * exposes no tools.
     */
    allowedToolNames?: string[];
    /** Optional denylist of tool names or patterns. When provided, matching tools are not exposed. */
    excludedToolNames?: string[];
    /**
     * Override base tools (useful for custom runtimes).
     *
     * These are synthesized into minimal ToolDefinitions internally so AgentSession can keep
     * a definition-first registry even when callers provide plain AgentTool instances.
     */
    baseToolsOverride?: Record<string, AgentTool>;
    /** Mutable ref used by Agent to access the current ExtensionRunner */
    extensionRunnerRef?: {
        current?: ExtensionRunner;
    };
    /** Session start event metadata emitted when extensions bind to this runtime. */
    sessionStartEvent?: SessionStartEvent;
}
export interface ExtensionBindings {
    uiContext?: ExtensionUIContext;
    mode?: ExtensionMode;
    commandContextActions?: ExtensionCommandContextActions;
    abortHandler?: () => void;
    shutdownHandler?: ShutdownHandler;
    onError?: ExtensionErrorListener;
}
export type QueuedInputDisposition = "handled" | "queued";
export type PromptDisposition = QueuedInputDisposition | "started";
/** Options for AgentSession.prompt() */
export interface PromptOptions {
    /** Whether to dispatch extension commands and expand skill commands and prompt templates (default: true) */
    expandPromptTemplates?: boolean;
    /** Image attachments */
    images?: ImageContent[];
    /** When streaming, how to queue the message: "steer" (interrupt) or "followUp" (wait). Required if streaming. */
    streamingBehavior?: "steer" | "followUp";
    /** Source of input for extension input event handlers. Defaults to "interactive". */
    source?: InputSource;
    /** Internal hook used by RPC mode to observe how an accepted prompt was dispatched. Not called if the prompt is rejected. */
    preflightResult?: (disposition: PromptDisposition) => void;
}
/** Options for model/thinking mutations. */
export interface ModelMutationOptions {
    /** Persist the new value to global defaults. Defaults to session-only. */
    persist?: boolean;
}
/** Result from cycleModel() */
export interface ModelCycleResult {
    model: Model<any>;
    thinkingLevel: ThinkingLevel;
    /** Whether cycling through scoped models (--models flag) or all available */
    isScoped: boolean;
}
/** Session statistics for /session command */
export interface SessionStats {
    sessionFile: string | undefined;
    sessionId: string;
    userMessages: number;
    assistantMessages: number;
    toolCalls: number;
    toolResults: number;
    totalMessages: number;
    tokens: {
        input: number;
        output: number;
        cacheRead: number;
        cacheWrite: number;
        total: number;
    };
    cost: number;
    contextUsage?: ContextUsage;
}
export declare class AgentSession {
    readonly agent: Agent;
    readonly sessionManager: SessionManager;
    readonly settingsManager: SettingsManager;
    private _scopedModels;
    private _unsubscribeAgent?;
    private _eventListeners;
    private _isAgentRunActive;
    private _promptPreflightCount;
    private _agentRunAbortRequested;
    private _idleWaitPromise;
    private _resolveIdleWait;
    /** Tracks pending steering messages for UI display. Removed when delivered. */
    private _steeringMessages;
    /** Tracks pending follow-up messages for UI display. Removed when delivered. */
    private _followUpMessages;
    /** Queued user messages whose images are normalized when they are delivered. */
    private _queuedMessagesWithImages;
    /** Messages queued to be included with the next user prompt as context ("asides"). */
    private _pendingNextTurnMessages;
    /** Context-only custom messages queued during a run, flushed once the current turn's tool results are in. */
    private _pendingCustomMessages;
    private _compactionAbortController;
    private _autoCompactionAbortController;
    private _overflowRecoveryAttempted;
    private _branchSummaryAbortController;
    private _retryAbortController;
    private _retryAttempt;
    /**
     * Failed response that the next request repeats, set by auto-retry and overflow recovery. The
     * retry is routed with it as `failed`, since the context no longer contains it.
     */
    private _failedResponse;
    private readonly _bashAbortControllers;
    private _pendingBashMessages;
    private _extensionRunner;
    private _turnIndex;
    private readonly _entryIdsByMessage;
    private readonly _boundaryDispatchedMessages;
    private _lastAssistantMessage;
    private _lastActivityOutcome;
    private _isBeforeSettle;
    private _abortDuringBeforeSettle;
    private _isEmittingAgentSettled;
    private readonly _deferredSettledActions;
    private _resourceLoader;
    private _customTools;
    private _baseToolDefinitions;
    private _cwd;
    private _extensionRunnerRef?;
    private _initialActiveToolNames?;
    /**
     * Tools of the restored or reloaded loadout that are not registered yet, such as tools of MCP
     * servers that are still connecting. They are activated when they are registered, and dropped when
     * `setActiveToolsByName()` deactivates a tool or the next agent run starts.
     */
    private _pendingToolNames;
    private _usesDefaultTools;
    private _defaultToolModifiers;
    /** Matches the `--tools` entries: tool names or patterns. */
    private _allowedTools?;
    /**
     * Whether the allowlist filters MCP tools: it is empty (`--no-tools`) or names an MCP tool
     * (`mcp__*`). Otherwise it keeps MCP tools registered for codemode and tool_search.
     */
    private _allowlistFiltersMcp;
    private _excludedTools?;
    private _baseToolsOverride?;
    private _sessionStartEvent;
    private _extensionUIContext?;
    private _extensionMode;
    private _extensionCommandContextActions?;
    private _extensionAbortHandler?;
    private _extensionShutdownHandler?;
    private _extensionErrorListener?;
    private _extensionErrorUnsubscriber?;
    private _modelRuntime;
    private _cacheWarmer?;
    private _toolRegistry;
    /** Created on the first `ctx.executeTool()` call. */
    private _nestedToolCalls;
    /** Declared tools whose declarations requests leave out, from `prepareLoadout` hooks. */
    private _hiddenDeclarations;
    private _toolDefinitions;
    private _toolPromptSnippets;
    private _toolPromptGuidelines;
    private _baseSystemPromptOptions;
    /** Prompt options after before_agent_start mutations for the active run. */
    private _runSystemPromptOptions?;
    constructor(config: AgentSessionConfig);
    get modelRuntime(): ModelRuntime;
    private _getRequiredRequestAuth;
    private _getSummarizationRequestAuth;
    /**
     * The model whose limits apply to `message`, or undefined when the message came from another
     * model. Under a virtual selection, that is the physical model that produced it.
     */
    private _modelForMessage;
    /** Record the live model and thinking level on the current branch, so a resume restores them. */
    private _recordSelection;
    /**
     * Record the model on the current branch when the branch implies another one. Tree navigation
     * can leave the latest `model_change` on another branch; responses cannot record a virtual
     * selection because they name physical models. Responses do record a physical selection unless
     * the branch holds a virtual one; checking a physical selection against responses would record
     * it on every prompt while `prepareRequest` redirects to another model.
     */
    private _recordModelSelection;
    /**
     * Record the thinking level on the current branch when the branch implies another one (#11451).
     * Tree navigation can leave the latest `thinking_level_change` on another branch. The recorded
     * level is compared after clamping to the current model, so a level clamped on resume (e.g.
     * `xhigh` running as `high`) is not recorded over the requested one.
     */
    private _recordThinkingLevel;
    /** The model whose limits apply to the conversation. */
    private _limitsModel;
    /**
     * Install tool hooks once on the Agent instance.
     *
     * The callbacks read `this._extensionRunner` at execution time, so extension reload swaps in the
     * new runner without reinstalling hooks. Extension-specific tool wrappers are still used to adapt
     * registered tool execution to the extension context. Tool call and tool result interception now
     * happens here instead of in wrappers.
     */
    private _installAgentToolHooks;
    /** `tool_call` handlers. `parentToolCallId` is set for calls another tool made. */
    private _beforeToolCall;
    /** `tool_result` handlers and image normalization. `parentToolCallId` is set for calls another tool made. */
    private _afterToolCall;
    /**
     * Run a call that the tool call `parentToolCallId` made through `ctx.executeTool()`. It goes
     * through the agent's tool pipeline with the session's hooks, against the callable tools.
     */
    private _executeNestedToolCall;
    /** Whether `projection`, the current session projection, exceeds the compaction threshold of `model`. */
    private _exceedsCompactionThreshold;
    private _compactBeforeNextAssistantResponse;
    private _installAgentRequestProjection;
    private _dispatchTurnEndBoundary;
    private _installAgentBoundaryHooks;
    private _installAgentNextTurnRefresh;
    private _refreshFinalizedContext;
    private _applyBoundaryDrafts;
    private _createBoundaryPreviewManager;
    private _getPendingBoundaryMessages;
    private _buildBoundaryContext;
    private _commitBoundaryDrafts;
    private _reportInvalidBoundaryContinuation;
    /** Emit an event to all listeners */
    private _emit;
    private _emitQueueUpdate;
    private _emitSessionCompactFailed;
    private _getIdleWaitPromise;
    private _resolveIdleWaitIfIdle;
    private _emitAgentSettled;
    /** Internal handler for agent events - shared by subscribe and reconnect */
    private _handleAgentEvent;
    private _willRetryAfterAgentEnd;
    private _findPersistedMessageEntryId;
    /**
     * Persistently omit a failed attempt and its tool results from model context. Results are
     * found in the projected context, so the pair stays together whether the attempt comes from
     * the current run or a resumed session. An unpaired result fails the next request (#11227).
     */
    private _omitRecoveryAttempt;
    /** Find the last assistant message in agent state (including aborted ones) */
    private _findLastAssistantMessage;
    private _replaceMessageInPlace;
    /** Emit extension events based on agent events */
    private _emitExtensionEvent;
    /**
     * Subscribe to agent events.
     * Session persistence is handled internally (saves messages on message_end).
     * Multiple listeners can be added. Returns unsubscribe function for this listener.
     */
    subscribe(listener: AgentSessionEventListener): () => void;
    /** Disconnect from agent events during disposal. */
    private _disconnectFromAgent;
    /**
     * Remove all listeners and disconnect from agent.
     * Call this when completely done with the session.
     */
    dispose(): void;
    /** Refresh the public finalized transcript from the canonical session projection. */
    refreshContext(): void;
    /** Full agent state */
    get state(): AgentState;
    /** Current cache-warming state and the policy inputs that produced it. */
    get cacheWarmingStatus(): CacheWarmingStatus | undefined;
    /** Persist the cache-warming mode and immediately reconcile active warming. */
    setCacheWarmingMode(mode: CacheWarmingMode): void;
    /** Current model (may be undefined if not yet selected) */
    get model(): Model<any> | undefined;
    /** Current thinking level */
    get thinkingLevel(): ThinkingLevel;
    /** Under a virtual selection, the physical model and thinking level of the latest successful response. */
    get routedModel(): {
        model: Model<any>;
        thinkingLevel?: ThinkingLevel;
    } | undefined;
    /** Whether the session is currently processing an agent run or post-run continuation. */
    get isStreaming(): boolean;
    /** Whether the session has no active agent run, compaction, branch summary, retry, or queued continuation. */
    get isIdle(): boolean;
    /** Current effective system prompt, including changes not yet sent to the model. */
    get systemPrompt(): string;
    /** Current retry attempt (0 if not retrying) */
    get retryAttempt(): number;
    /**
     * Get the names of currently active tools, which are the tools declared to the model.
     * Tools with `codemode` or `deferred` exposure are callable from other tools without being active.
     */
    getActiveToolNames(): string[];
    /** Get the names of the tools that tools can call through `ctx.executeTool()`. */
    getCallableToolNames(): string[];
    /**
     * Get all configured tools with name, description, parameter schema, prompt guidelines, and source metadata.
     */
    getAllTools(): ToolInfo[];
    getToolDefinition(name: string): ToolDefinition | undefined;
    /**
     * Set active tools by name.
     * Only tools in the registry can be enabled. Unknown and hidden tool names are ignored.
     * Also rebuilds the system prompt to reflect the new tool set.
     * Changes take effect on the next agent turn.
     */
    setActiveToolsByName(toolNames: string[]): void;
    private _setActiveTools;
    /**
     * Whether `--tools` and `--exclude-tools` keep the tool registered. MCP tools stay registered
     * unless the allowlist filters them (see `_allowlistFiltersMcp`).
     */
    private _isAllowedTool;
    /**
     * Whether the tool may be active, which declares it to the model. MCP tools the allowlist keeps
     * without matching them are only for codemode and tool_search: they may be declared only when
     * tool_search can load them (non-`direct` exposure and tool_search registered). This also applies
     * to tools restored from the transcript or set by extensions.
     */
    private _isActivatable;
    private _getToolExposure;
    /**
     * Tools callable through `ctx.executeTool()`: the active `direct` tools and every registered
     * `codemode` or `deferred` tool.
     */
    private _getCallableTools;
    /**
     * Set the agent's tools for the given active tool names and return them. The active tools are
     * the registered, non-hidden ones; they are declared to the model. Active tools with a
     * `prepareLoadout` hook can change the declared descriptions and hide declarations from
     * requests (see {@link _installHiddenDeclarationsProjection}).
     *
     * The active tools are a set: tools that stay active keep their current order and newly active
     * ones are appended, so reordering the same names does not change the prompt (#11495).
     */
    private _applyToolLoadout;
    /** Whether compaction or branch summarization is currently running */
    get isCompacting(): boolean;
    /** All messages including custom types like BashExecutionMessage */
    get messages(): AgentMessage[];
    /** Current steering mode */
    get steeringMode(): "all" | "one-at-a-time";
    /** Current follow-up mode */
    get followUpMode(): "all" | "one-at-a-time";
    /** Current session file path, or undefined if sessions are disabled */
    get sessionFile(): string | undefined;
    /** Current session ID */
    get sessionId(): string;
    /** Current session display name, if set */
    get sessionName(): string | undefined;
    /** Scoped models for cycling (from --models flag) */
    get scopedModels(): ReadonlyArray<{
        model: Model<any>;
        thinkingLevel?: ThinkingLevel;
    }>;
    /** Update scoped models for cycling */
    setScopedModels(scopedModels: Array<{
        model: Model<any>;
        thinkingLevel?: ThinkingLevel;
    }>): void;
    /** File-based prompt templates */
    get promptTemplates(): ReadonlyArray<PromptTemplate>;
    private _normalizePromptSnippet;
    private _normalizePromptGuidelines;
    private _rebuildSystemPrompt;
    /**
     * Apply a prompt and tool loadout for the next request. Sets the executable tools and
     * returns a system message patching the prompt sections the model currently has (replayed
     * from `messages`), or undefined when the prompt is unchanged. Tool changes are declared by
     * the agent loop before the request.
     *
     * A forced prompt does not affect the transcript: the structured sections are still diffed
     * and persisted, and the forced text is projected onto the request by
     * {@link _installAgentForcedPromptProjection}.
     */
    private _preparePromptAndToolLoadout;
    /**
     * Send a forced prompt as the provider's leading system prompt without recording it.
     *
     * A `before_agent_start` handler that returns `systemPrompt` needs that exact text at the
     * head of the request; a mid-conversation system message would leave the original prompt
     * in place. The forced text is a rendering of the current prompt, so the transcript keeps
     * its structured sections and the request is projected instead: the system messages
     * collapse into one head holding the forced text and the current tools. Runs after the
     * `context` extension handlers.
     */
    /**
     * Remove the declarations that `prepareLoadout` hooks hide from every request. The whole
     * transcript is filtered with the current set, so the projected declarations stay consistent
     * across requests and only change when the loadout does.
     */
    private _installHiddenDeclarationsProjection;
    private _installAgentForcedPromptProjection;
    /**
     * Restore the active tool loadout declared by the session transcript, if it declares one.
     * Tools reachable only from other tools are never declared, but they do not depend on the active
     * set, so the transcript's declarations are the whole loadout.
     * @param modifiers `+name`/`-name` entries applied to the restored loadout.
     */
    private _restoreToolsFromTranscript;
    /**
     * Start a run from a user or custom message. The session counts as busy from here on, so
     * messages sent while before_agent_start handlers run are queued into this run instead of
     * starting another, and an abort requested meanwhile aborts the run as soon as it exists.
     * @param onStarted Called once the run's messages are prepared, before the first request.
     */
    private _startRun;
    /**
     * Prepare a run and return its starting messages: compact first when needed, emit
     * before_agent_start, apply the run's prompt options and tool loadout, and build the starting
     * message followed by pending nextTurn messages (consumed here) and handler messages, with a
     * system patch first when the prompt changed.
     */
    private _prepareRun;
    private _handlePostAgentRun;
    private _runBeforeSettleBoundary;
    private _runInputHandlers;
    private _normalizePromptImages;
    /**
     * Send a prompt to the agent.
     * - Handles extension commands (registered via pi.registerCommand) immediately, even during streaming
     * - Expands file-based prompt templates by default
     * - During streaming, queues via steer() or followUp() based on streamingBehavior option
     * - Validates model and API key before sending (when not streaming)
     * @throws Error if streaming and no streamingBehavior specified
     * @throws Error if no model selected or no API key available (when not streaming)
     */
    prompt(text: string, options?: PromptOptions): Promise<void>;
    /**
     * Run input hooks, expand templates, queue while streaming, and validate model and auth.
     * Returns the run trigger, or undefined when the prompt was handled or queued.
     */
    private _preparePrompt;
    /**
     * Try to execute an extension command. Returns true if command was found and executed.
     */
    private _tryExecuteExtensionCommand;
    /**
     * Expand skill commands (/skill:name args) to their full content.
     * Returns the expanded text, or the original text if not a skill command or skill not found.
     * Emits errors via extension runner if file read fails.
     */
    private _expandSkillCommand;
    private _queueUserInput;
    /**
     * Queue a steering message while the agent is running.
     * Delivered after the current assistant turn finishes executing its tool calls,
     * before the next LLM call.
     * Expands skill commands and prompt templates. Errors on extension commands.
     * @param images Optional image attachments to include with the message
     * @param options Input source; defaults to interactive
     * @throws Error if text is an extension command
     */
    steer(text: string, images?: ImageContent[], options?: {
        source?: InputSource;
    }): Promise<QueuedInputDisposition>;
    /**
     * Queue a follow-up message to be processed after the agent finishes.
     * Delivered only when agent has no more tool calls or steering messages.
     * Expands skill commands and prompt templates. Errors on extension commands.
     * @param images Optional image attachments to include with the message
     * @param options Input source; defaults to interactive
     * @throws Error if text is an extension command
     */
    followUp(text: string, images?: ImageContent[], options?: {
        source?: InputSource;
    }): Promise<QueuedInputDisposition>;
    /**
     * Internal: Queue a steering message (already expanded, no extension command check).
     */
    private _queueSteer;
    /**
     * Internal: Queue a follow-up message (already expanded, no extension command check).
     */
    private _queueFollowUp;
    /** Replace a queued user message's images in place with normalized ones, appending hints to its text. */
    private _normalizeQueuedMessageImages;
    /**
     * Throw an error if the text is an extension command.
     */
    private _throwIfExtensionCommand;
    /**
     * Send a custom message to the session. Creates a CustomMessageEntry.
     *
     * Handles four cases:
     * - Streaming: queues message, processed when loop pulls from queue
     * - Streaming + triggerTurn false: appended to state/session once the current turn ends
     * - Not streaming + triggerTurn: appends to state/session, starts new turn
     * - Not streaming + no trigger: appends to state/session, no turn
     *
     * @param message Custom message with customType, content, display, details
     * @param options.triggerTurn If true and not streaming, triggers a new LLM turn
     * @param options.deliverAs Delivery mode: "steer", "followUp", or "nextTurn"
     */
    sendCustomMessage<T = unknown>(message: Pick<CustomMessage<T>, "customType" | "content" | "display" | "details">, options?: {
        triggerTurn?: boolean;
        deliverAs?: "steer" | "followUp" | "nextTurn";
    }): Promise<void>;
    private _appendCustomMessage;
    /**
     * Append custom messages queued while the agent was running.
     * Called once the current turn's tool results are in agent state and session history.
     */
    private _flushPendingCustomMessages;
    /**
     * Send a user message to the agent. Always triggers a turn.
     * When the agent is streaming, use deliverAs to specify how to queue the message.
     *
     * @param content User message content (string or content array)
     * @param options.deliverAs Delivery mode when streaming: "steer" or "followUp"
     * @param options.expandPromptTemplates Whether to dispatch extension commands and expand skill commands and prompt templates. Default: false.
     */
    sendUserMessage(content: string | (TextContent | ImageContent)[], options?: {
        deliverAs?: "steer" | "followUp";
        expandPromptTemplates?: boolean;
    }): Promise<void>;
    /**
     * Clear all queued messages and return them.
     * Useful for restoring to editor when user aborts.
     * @returns Object with steering and followUp arrays
     */
    clearQueue(): {
        steering: string[];
        followUp: string[];
    };
    /** Number of pending messages (includes both steering and follow-up) */
    get pendingMessageCount(): number;
    /** Get pending steering messages (read-only) */
    getSteeringMessages(): readonly string[];
    /** Get pending follow-up messages (read-only) */
    getFollowUpMessages(): readonly string[];
    get resourceLoader(): ResourceLoader;
    /**
     * Abort current operation and wait for agent to become idle.
     */
    abort(): Promise<void>;
    waitForIdle(): Promise<void>;
    private _emitModelSelect;
    /**
     * Set model directly.
     * Validates that auth is configured and saves to the session transcript.
     * Persists to global defaults only when options.persist is true.
     * @throws Error if no auth is configured for the model
     */
    setModel(model: Model<any>, options?: ModelMutationOptions): Promise<void>;
    private _addPersistedDefaultToNonEmptyScope;
    /**
     * Cycle to next/previous model.
     * Uses scoped models (from --models flag) if available, otherwise all available models.
     * @param direction - "forward" (default) or "backward"
     * @returns The new model info, or undefined if only one model available
     */
    cycleModel(direction?: "forward" | "backward", options?: ModelMutationOptions): Promise<ModelCycleResult | undefined>;
    private _cycleScopedModel;
    private _cycleAvailableModel;
    /**
     * Set thinking level.
     * Clamps to model capabilities based on available thinking levels.
     * Saves the clamped level to the session transcript only if the level actually changes.
     * Persists the requested level to global defaults only when options.persist is true.
     */
    setThinkingLevel(level: ThinkingLevel, options?: ModelMutationOptions): void;
    /**
     * Cycle to next thinking level.
     * @returns New level, or undefined if model doesn't support thinking
     */
    cycleThinkingLevel(options?: ModelMutationOptions): ThinkingLevel | undefined;
    /**
     * Get available thinking levels for current model.
     * The provider will clamp to what the specific model supports internally.
     */
    getAvailableThinkingLevels(): ThinkingLevel[];
    /**
     * Check if current model supports thinking/reasoning.
     */
    supportsThinking(): boolean;
    private _getThinkingLevelForModelSwitch;
    private _clampThinkingLevel;
    private syncQueueModesFromSettings;
    /**
     * Set steering message mode.
     * Saves to settings.
     */
    setSteeringMode(mode: "all" | "one-at-a-time"): void;
    /**
     * Set follow-up message mode.
     * Saves to settings.
     */
    setFollowUpMode(mode: "all" | "one-at-a-time"): void;
    /** Generate Pi's built-in compaction summary for manual and automatic compaction. */
    private _runDefaultCompaction;
    private _clearManualCompactionState;
    /**
     * Manually compact the session context.
     *
     * This is the manual entry point used by `/compact`, RPC, and extensions. It is
     * separate from automatic threshold/overflow compaction, which enters through
     * `_checkCompaction()` and `_runAutoCompaction()`. After preparation and the
     * `session_before_compact` hook, both paths call the lower-level `compact()`
     * function imported from `./compaction/index.ts`, unless the hook cancels or
     * supplies a custom result.
     *
     * Aborts the current agent operation first. Manual compaction never retries or
     * continues the interrupted agent turn.
     *
     * @param customInstructions Optional instructions for the compaction summary
     */
    compact(customInstructions?: string): Promise<CompactionResult>;
    /**
     * Cancel in-progress compaction (manual or auto).
     */
    abortCompaction(): void;
    /**
     * Cancel in-progress branch summarization.
     */
    abortBranchSummary(): void;
    /**
     * Dispatch automatic compaction after `agent_end` or before prompt submission.
     * Manual compaction does not call this method; it enters through `compact()`.
     *
     * Automatic cases:
     * 1. Overflow with retry: a context-overflow error or recoverable length stop;
     *    remove the failed assistant message, compact, and retry the turn once.
     * 2. Overflow without retry: a successful response exceeded the configured
     *    context window; compact but preserve the completed response.
     * 3. Threshold without retry: valid or estimated context usage crossed the
     *    configured threshold; compact without retrying the completed response.
     *
     * Each case calls `_runAutoCompaction()`. After preparation and the
     * `session_before_compact` hook, that method calls the lower-level `compact()`
     * function imported from `./compaction/index.ts`, unless the hook cancels or
     * supplies a custom result.
     *
     * @param assistantMessage The assistant message to check
     * @param skipAbortedCheck If false, include aborted messages (for pre-prompt check). Default: true
     * @returns Whether the post-run loop should call `agent.continue()` for overflow recovery or queued messages
     */
    private _checkCompaction;
    /**
     * Execute threshold or overflow compaction. Manual compaction uses
     * `AgentSession.compact()` instead. Both paths call the lower-level `compact()`
     * function imported from `./compaction/index.ts` after preparation and extension
     * interception.
     *
     * @param reason Automatic trigger selected by `_checkCompaction()`
     * @param willRetry Whether to continue the interrupted turn after overflow compaction
     * @returns Whether the post-run loop should call `agent.continue()`
     */
    private _runAutoCompaction;
    /**
     * Toggle auto-compaction setting.
     */
    setAutoCompactionEnabled(enabled: boolean): void;
    /** Whether auto-compaction is enabled */
    get autoCompactionEnabled(): boolean;
    bindExtensions(bindings: ExtensionBindings): Promise<void>;
    private extendResourcesFromExtensions;
    private buildExtensionResourcePaths;
    private getExtensionSourceLabel;
    private _applyExtensionBindings;
    private _refreshCurrentModelFromRegistry;
    private _bindExtensionCore;
    private _refreshToolRegistry;
    /** Whether activating the tool declares it to the model. */
    private _isDeclarable;
    /** Whether registering the tool activates it, which declares it to the model. */
    private _isActivatedOnRegistration;
    private _buildRuntime;
    reload(options?: {
        beforeSessionStart?: () => void | Promise<void>;
    }): Promise<void>;
    /**
     * Check if an error is retryable (overloaded, rate limit, server errors).
     * Context overflow errors are NOT retryable (handled by compaction instead).
     */
    private _isRetryableError;
    /**
     * Retry policy + callbacks shared by compaction and branch-summary summarization calls.
     * Uses the same `settings.retry` budget/backoff as agent-turn retries so a single transient
     * stream drop no longer fails the whole operation. `source` carries the context
     * the TUI needs to render the retry and recreate the underlying indicator.
     */
    private _summarizationRetryCallbacks;
    private _finishCancelledRetry;
    /**
     * Prepare a retryable error for continuation with exponential backoff.
     * @returns true if the caller should continue the agent, false otherwise
     */
    private _prepareRetry;
    /**
     * Cancel in-progress retry.
     */
    abortRetry(): void;
    /** Whether auto-retry is currently in progress */
    get isRetrying(): boolean;
    /** Whether auto-retry is enabled */
    get autoRetryEnabled(): boolean;
    /**
     * Toggle auto-retry setting.
     */
    setAutoRetryEnabled(enabled: boolean): void;
    /**
     * Execute a bash command.
     * Adds result to agent context and session.
     * @param command The bash command to execute
     * @param onChunk Optional streaming callback for output
     * @param options.excludeFromContext If true, command output won't be sent to LLM (!! prefix)
     * @param options.id Optional identifier included in bash execution update events
     * @param options.operations Custom BashOperations for remote execution
     */
    executeBash(command: string, onChunk?: (chunk: string) => void, options?: {
        excludeFromContext?: boolean;
        id?: string;
        operations?: BashOperations;
    }): Promise<BashResult>;
    /**
     * Record a bash execution result in session history.
     * Used by executeBash and by extensions that handle bash execution themselves.
     */
    recordBashResult(command: string, result: BashResult, options?: {
        excludeFromContext?: boolean;
    }): void;
    /**
     * Cancel running bash command.
     */
    abortBash(): void;
    /** Whether a bash command is currently running */
    get isBashRunning(): boolean;
    /** Whether there are pending bash messages waiting to be flushed */
    get hasPendingBashMessages(): boolean;
    /**
     * Flush pending bash messages to agent state and session.
     * Called after agent turn completes to maintain proper message ordering.
     */
    private _flushPendingBashMessages;
    /**
     * Set a display name for the current session.
     */
    setSessionName(name: string): void;
    /**
     * Navigate to a different node in the session tree.
     * Unlike fork() which creates a new session file, this stays in the same file.
     *
     * @param targetId The entry ID to navigate to
     * @param options.summarize Whether user wants to summarize abandoned branch
     * @param options.customInstructions Custom instructions for summarizer
     * @param options.replaceInstructions If true, customInstructions replaces the default prompt
     * @param options.label Label to attach to the branch summary entry
     * @returns Result with editorText (if user message) and cancelled status
     */
    navigateTree(targetId: string, options?: {
        summarize?: boolean;
        customInstructions?: string;
        replaceInstructions?: boolean;
        label?: string;
    }): Promise<{
        editorText?: string;
        cancelled: boolean;
        aborted?: boolean;
        summaryEntry?: BranchSummaryEntry;
    }>;
    /**
     * Get all user messages from session for fork selector.
     */
    getUserMessagesForForking(): Array<{
        entryId: string;
        text: string;
    }>;
    /**
     * Get session statistics. Aggregates over ALL session entries (including
     * history that was compacted away), so token/cost totals reflect what was
     * actually billed across the session.
     */
    getSessionStats(): SessionStats;
    getContextUsage(): ContextUsage | undefined;
    /**
     * Export session to HTML.
     * @param outputPath Optional output path (defaults to session directory)
     * @param options Optional export presentation settings
     * @returns Path to exported file
     */
    exportToHtml(outputPath?: string, options?: {
        themeName?: string;
    }): Promise<string>;
    /**
     * Export the current session branch to a JSONL file.
     * Writes the session header followed by all entries on the current branch path.
     * @param outputPath Target file path. If omitted, generates a timestamped file in cwd.
     * @returns The resolved output file path.
     */
    exportToJsonl(outputPath?: string): string;
    /**
     * Ask the current model to describe what went wrong in this session for a bug report.
     * Used when the user declines to share the transcript itself.
     */
    summarizeForBugReport(options: {
        hint?: string;
        signal: AbortSignal;
    }): Promise<string>;
    /**
     * Get text content of last assistant message.
     * Useful for /copy command.
     * @returns Text content, or undefined if no assistant message exists
     */
    getLastAssistantText(): string | undefined;
    createReplacedSessionContext(): ReplacedSessionContext;
    /**
     * Check if extensions have handlers for a specific event type.
     */
    hasExtensionHandlers(eventType: string): boolean;
    /**
     * Get the extension runner (for setting UI context and error handlers).
     */
    get extensionRunner(): ExtensionRunner;
}
export {};
//# sourceMappingURL=agent-session.d.ts.map