import { type AgentTool } from "@kenkaiiii/gg-agent";
import { type Message, type Provider, type ThinkingLevel } from "@kenkaiiii/gg-ai";
import { EventBus } from "./event-bus.js";
import { SlashCommandRegistry } from "./slash-commands.js";
import { type BranchInfo, type KenTurnPayload, type AutopilotMarkerPayload, type AppMarkerPayload, type TurnMetricPayload } from "./session-manager.js";
import type { BackgroundProcess } from "./process-manager.js";
import { type EnhanceResult } from "../utils/prompt-enhancer.js";
/** A chat attachment (image / video / other file) prepared for the model. The
 *  raw base64 `data` rides native blocks; `path` (when persisted to disk) lets
 *  the agent's tools open the file directly. */
export interface SessionAttachment {
    kind: "image" | "video" | "file";
    mediaType: string;
    data: string;
    name: string;
    path?: string;
}
export interface AgentSessionOptions {
    provider: Provider;
    model: string;
    cwd: string;
    baseUrl?: string;
    systemPrompt?: string;
    /** Synchronous volatile prompt suffix, refreshed immediately before every run. */
    getSystemPromptTail?: () => string;
    sessionId?: string;
    continueRecent?: boolean;
    maxTokens?: number;
    maxTurns?: number;
    /**
     * How many times the turn budget may be extended when the agent is still
     * making progress. Defaults to the agent-loop default (2); sub-agents pass a
     * stricter cap because a child's extensions multiply against the parent's
     * own budget.
     */
    maxTurnExtensions?: number;
    thinkingLevel?: ThinkingLevel;
    signal?: AbortSignal;
    /** Prefix used for provider prompt-cache routing keys. */
    promptCacheKeyPrefix?: string;
    /**
     * Explicit prompt-cache routing key. When set, overrides the
     * `${promptCacheKeyPrefix}:${sessionId}` default so spawned sub-agents can
     * inherit a stable parent-scoped key — without this, each sub-agent process
     * generates a fresh sessionId and starts with a cold cache.
     */
    promptCacheKey?: string;
    /**
     * If true, this session does NOT create a `.jsonl` session file or persist
     * any messages. Used by subagent spawns (`--json` mode) so their transcripts
     * don't leak into `ggcoder continue` for the parent project. Subagent runs
     * are one-shot, NDJSON-streamed to the parent over stdout, and have no
     * resumable identity.
     */
    transient?: boolean;
    /**
     * If true, `initialize()` returns WITHOUT waiting for MCP servers to connect —
     * the connection runs in the background and tools are appended when ready.
     * Hosts whose readiness is gated on `initialize()` (the gg-app sidecar, which
     * can't emit its listening handshake until init resolves) set this so a slow
     * or hanging stdio MCP server (e.g. a first-run `npx -y …` download) can't
     * delay the session from becoming usable. Default (false) keeps the CLI's
     * connect-before-ready behavior so MCP tools are present on the first turn.
     */
    backgroundMcpConnect?: boolean;
    /**
     * If true, an over-context restored session is NOT compacted inline during
     * `loadExistingSession()` — the existing pre-run auto-compaction in
     * `runLoop()` handles it on the first prompt instead (with proper
     * compaction_start/_end events). The inline load compaction makes a summary
     * LLM call with a 30s timeout, and hosts whose readiness is gated on
     * `initialize()` (the gg-app sidecar: waitForReady blocks the whole webview)
     * would freeze the UI for that entire call. Default (false) keeps the
     * compact-on-load behavior for CLI resume/`ggcoder continue`.
     */
    deferLoadCompaction?: boolean;
    /**
     * Plan-mode callbacks. When provided, the `enter_plan`/`exit_plan` tools are
     * registered and the session manages plan-mode restrictions + system-prompt
     * rebuilds. Hosts (e.g. the gg-app sidecar) use these to surface plan-mode
     * UI. Omitted by callers that don't want plan mode (CLI wires its own).
     */
    onEnterPlan?: (reason?: string) => void | Promise<void>;
    onExitPlan?: (planPath: string) => Promise<string>;
    /**
     * If provided, the session's tool set is filtered to ONLY these tool names
     * after `createTools()` runs, and the system prompt's Tools section lists only
     * them. Used by read-only advisory sessions (e.g. the Ken mentor agent) to
     * register a safe subset — excluded mutating tools (write/edit/bash/…) are
     * never registered, so a hallucinated call can't change the repo. Default
     * (undefined) = all tools, preserving every existing caller's behavior.
     */
    allowedTools?: string[];
    /**
     * MCP server names whose tools are allowed in an allow-listed session. Only
     * meaningful alongside `allowedTools`. With it set, the session connects ONLY
     * these named MCP servers (not the full configured set) and every tool they
     * expose (`mcp__<server>__*`) passes the allow-list. The Ken mentor agent uses
     * this to get `kencode-search` for real-code research while still being barred
     * from every mutating tool. Empty/undefined → an allow-listed session skips
     * MCP entirely (its dynamic tool names could never match a fixed allow-list).
     */
    allowedMcpServers?: string[];
    /**
     * Force 1-h prompt-cache TTL + pre-warm regardless of the user's global
     * `speedProfile` setting. Bursty read-only advisory sessions (the Ken
     * mentor + autopilot reviewer) call the same static system prompt on a
     * schedule that routinely exceeds the default 5-min cache window — a
     * dropped cache there resends the whole cached prefix at full price right
     * when it matters most, independent of whatever the user picked for the
     * main build session. Default (undefined) = follow `speedProfile`.
     */
    forceLongCacheRetention?: boolean;
    /** Hidden persistent subagent workers omit the async orchestration tool suite. */
    subagentWorker?: boolean;
    /** Session storage root override. Chat agents use a dedicated namespace. */
    sessionRootDir?: string;
    /** Register GG Coder built-in/prompt/custom slash commands. Defaults to true. */
    coderSlashCommands?: boolean;
    /** Enable loop-break, re-grounding, and Ideal review hooks. Defaults to true. */
    selfCorrectionHooks?: boolean;
    /** Load project skills/agents and create local .gg directories. Defaults to true. */
    projectCustomization?: boolean;
    /** Register global + bundled subagents without loading project customization. */
    globalSubagents?: boolean;
    /** Load GG Coder extensions. Defaults to true. */
    loadExtensions?: boolean;
    /** Inject GG Coder's model-specific subagent orchestration prompt. Defaults to true. */
    orchestrationPrompt?: boolean;
    /** Host-provided tools appended to this session only (for example, chat delegation). */
    additionalTools?: AgentTool[];
}
/** Resolve the per-result cap passed to the agent loop for the active transport. */
export declare function resolveSessionToolResultCharLimit(model: string, provider: Provider, accountId?: string): number;
/**
 * Aggregate budget for ALL tool results produced in one assistant turn.
 * Individual results are already capped, but wide parallel fan-outs (GPT-5.6's
 * signature behavior) were observed injecting 100k+ uncached tokens in a single
 * turn. ~15% of the context window in chars (1 token ≈ 3.5 chars), floored at
 * 100KB so small windows still fit two full-size reads, ceilinged at 240KB so
 * 1M-context models don't waive the budget entirely.
 */
export declare function resolveSessionTurnToolResultCharLimit(model: string, provider: Provider, accountId?: string): number;
export interface AgentSessionState {
    provider: Provider;
    model: string;
    cwd: string;
    sessionId: string;
    sessionPath: string;
    messageCount: number;
    planMode: boolean;
    /** accountId from the most recently resolved credentials, if any — lets
     *  callers compute the transport-specific context window (e.g. OpenAI Codex
     *  OAuth) without re-resolving credentials. */
    accountId?: string;
}
export declare class AgentSession {
    readonly eventBus: EventBus;
    readonly slashCommands: SlashCommandRegistry;
    private settingsManager;
    private authStorage;
    private sessionManager;
    private extensionLoader;
    private messages;
    private kenTurns;
    private autopilotMarkers;
    private appMarkers;
    private turnMetrics;
    private tools;
    /** Rebuilds the read tool for a new model (video byte cap is baked in at
     *  creation). Called from switchModel so video-capable models get the
     *  read-tool's native-video path after a mid-session model change. */
    private rebuildReadTool;
    private skills;
    private cacheKeyLogged;
    private hookStats;
    private hookText;
    private hookConsecutiveFailures;
    private hookRepeatedNoProgressCalls;
    private hookProgressTracker;
    private hookCycleDetector;
    private hookCyclicPattern;
    private hookFileEditCounts;
    private hookToolCalls;
    private idealReviewPhase;
    /** Runtime-only suppression while Ken owns verification in autopilot mode. */
    private idealReviewSuppressed;
    private readonly reviewCoverage;
    /** 0 = none; 1 = first nudge sent; 2 = final stop-and-report injected. */
    private loopBreakInjected;
    private regroundingInjected;
    private compactionOccurred;
    private lastCompactionCompacted;
    private compactionRetryAfter;
    /** Latest provider count, anchored to the assistant response it measured. */
    private providerContext;
    private originalRequest;
    private userQueue;
    private queueSeq;
    private processManager?;
    private lspManager?;
    private subAgentManager?;
    /**
     * Out-of-band push notifications (finished children, background-process
     * progress). Producers enqueue; `getHookSteeringMessages` drains into the
     * live turn so the agent never has to spend a turn asking.
     */
    private readonly notifications;
    private managerAbortSignal?;
    private readonly managerAbortHandler;
    private mcpManager?;
    /** Deferred MCP tools awaiting discovery via tool_search (bench A win). */
    private mcpCatalog?;
    private provider;
    private model;
    private cwd;
    /** accountId from the most recently resolved credentials — cached so sync
     *  callers (e.g. the app-sidecar's context-window footer stat) can reflect
     *  transport-specific windows (e.g. OpenAI Codex OAuth's smaller window)
     *  without re-resolving credentials on every poll. */
    private lastAccountId?;
    private baseUrl?;
    private maxTokens;
    private thinkingLevel?;
    private customSystemPrompt?;
    /** Stable prompt prefix retained separately from the volatile uncached tail. */
    private baseSystemPrompt;
    /** Shared with the tool layer so plan-mode restrictions read live state. */
    private planModeRef;
    /** Path of the approved plan currently being implemented, or undefined. When
     *  set, the system prompt carries the `[DONE:n]` progress contract so the
     *  model emits step-completion markers the UI's plan-progress widget reads. */
    private approvedPlanPath?;
    /** Extra workspace roots added with `/add-dir` (resolved, de-duplicated). */
    private additionalRoots;
    private sessionId;
    /** Stable identity shared by compaction and approved-plan checkpoint files. */
    private conversationId;
    /** Original user-authored prompt, retained when internal messages replace history. */
    private sessionPreview;
    /** Runtime conversation identity for provider transport headers. Transient
     *  children need one even though they intentionally have no persisted session. */
    private readonly transportSessionId;
    private sessionPath;
    private lastPersistedIndex;
    /**
     * Number of non-system messages guaranteed to be in the session file — the
     * anchor base for transcript markers (Ken turns, autopilot verdicts, app
     * markers). `this.messages` can run ahead of the file: the agent loop
     * appends assistant/tool/steering messages in place but they are only
     * persisted when the run SUCCEEDS, so after a failed run the in-memory list
     * carries an unpersisted tail. Markers anchored against that tail point past
     * their real position on resume — the row (notably an error) renders lower
     * in the transcript than it happened, bunching at the bottom, or gets
     * dropped as out-of-range. Anchoring to the persisted prefix keeps resume
     * placement 1:1 with where the row appeared live.
     */
    private persistedTranscriptCount;
    /** Current leaf entry ID in the session DAG — used to chain parentIds for branching. */
    private currentLeafId;
    private opts;
    constructor(options: AgentSessionOptions);
    /**
     * Derive the output-token cap for a model. Follows the active model's
     * `maxOutputTokens` so a session booted on a large-output model (e.g. Kimi's
     * 256K) doesn't carry that cap to a smaller one (e.g. Opus's 128K) after a
     * model switch — that mismatch surfaces from the provider as
     * `max_tokens: 262144 > 128000, which is the maximum allowed …`. An explicit
     * `maxTokens` override is honored but clamped to the model's ceiling.
     */
    private resolveMaxTokens;
    initialize(): Promise<void>;
    /**
     * Whether a tool name is permitted for this session. With no `allowedTools`
     * everything passes (default behavior). Otherwise a tool is allowed when its
     * name is in `allowedTools`, OR it's an MCP tool (`mcp__<server>__<tool>`)
     * whose `<server>` is in `allowedMcpServers`. The MCP-prefix rule lets a
     * whitelisted research server (e.g. kencode-search) expose all its tools
     * without hard-coding each one, while every other tool stays blocked.
     */
    private isToolAllowed;
    /**
     * Connect all configured MCP servers and append their tools to `this.tools`.
     * Resolves the GLM api key first (Z.AI's bundled servers need it). Never
     * throws — a failed connect is logged and skipped — so it is safe to either
     * `await` (CLI: tools ready before the first turn) or fire-and-forget
     * (sidecar: `backgroundMcpConnect`, so a slow stdio server can't stall
     * startup). Tools are pushed onto the live array the agent loop reads each
     * turn, so background-connected servers become available on the next prompt.
     */
    private connectMcpServers;
    /**
     * Route freshly connected MCP tools: deferred into the tool_search catalog
     * (default — keeps ~8k tokens of schema out of every cache-miss turn, see
     * bench/RESULTS.md bench A) or pushed eagerly when the user opted out.
     * Allow-listed sessions (Ken) always get the eager path — their fixed tool
     * expectations predate the catalog, and tool_search isn't allow-listed.
     * Promotion pushes onto the live `this.tools` array the running agent loop
     * re-reads every turn, so promoted tools are callable on the next step.
     */
    private addMcpTools;
    /**
     * Resolve a `/name [args]` input to the prompt template it expands into, or
     * null when it isn't a prompt-template command for THIS session (an ordinary
     * message, a registry/action command, or any slash input on a non-coder
     * agent). Shared by {@link prompt} and {@link willExpandPromptTemplate} so
     * callers can't drift from the expansion that actually happens.
     */
    private resolveSlashInput;
    /**
     * Whether {@link prompt} would expand this input into a template body and
     * persist it as a user message. Hosts use it to record the typed `/name` for
     * transcript restore — gating on anything looser risks tagging an unrelated
     * message when the command turns out NOT to expand.
     */
    willExpandPromptTemplate(content: string): Promise<boolean>;
    /**
     * Process user input. Handles slash commands or runs agent loop.
     */
    prompt(content: string): Promise<void>;
    /**
     * Prompt with multimodal attachments (images / videos) alongside optional
     * text. Images and videos become native content blocks the model can see;
     * non-media files are surfaced as a text note with their saved path so the
     * agent can open them with its tools. Slash-command parsing is skipped —
     * attachments are always a direct conversational turn.
     */
    promptWithAttachments(text: string, attachments: SessionAttachment[]): Promise<void>;
    /**
     * Build the native content blocks (text + image/video notes + file notes) for
     * a user message with attachments. Shared by {@link promptWithAttachments} and
     * the mid-run steering drain so queued media is delivered identically.
     */
    private buildAttachmentParts;
    /**
     * Reset per-run self-correction hook state. Mirrors the TUI's run_start
     * resets so each run evaluates the hooks from a clean slate. `originalRequest`
     * is the verbatim user ask, pinned for post-compaction re-grounding.
     */
    private resetHookState;
    /**
     * Fold one agent event into the hook stat accumulators. Pure bookkeeping —
     * the same signals the TUI's useAgentLoop collects, so the loop-break and
     * ideal-review decisions match across the CLI and the app.
     */
    private trackHookEvent;
    /**
     * Mid-loop steering hook: delivers pushed notifications and queued user
     * steering, fires the loop-breaker when the agent looks stuck, then
     * post-compaction re-grounding. At most one loop-break/re-grounding per run.
     * Mirrors the TUI's getSteeringMessages ordering.
     */
    private getHookSteeringMessages;
    /**
     * Turn-budget extension gate. The loop consults this instead of stopping
     * mid-task when it exhausts `maxTurns`. Grant ONLY on evidence of progress —
     * handing more turns to a spinning agent just buys it more tokens to spin
     * with — so reuse the same stuck signals that drive the loop-breaker.
     */
    private shouldExtendTurnBudget;
    /**
     * Pre-stop Ideal review phase machine. Once review starts, completion is
     * blocked until harness-owned post-injection reads cover every changed file.
     */
    private getHookFollowUpMessages;
    private reviewLspEvidence;
    private withReviewLspEvidence;
    /** Auto-compact if needed, run agent loop with auth retry, and persist messages. */
    private runLoop;
    switchModel(provider: string, model: string): Promise<void>;
    /**
     * Record the switch as its own trailing message at the point it happened,
     * rather than by rewriting the system prompt. Two reasons: the system prompt
     * is the cached prefix and rewriting it costs a full cache write, and a
     * resumed transcript can only attribute output to the right model if the
     * switch sits in message order.
     *
     * Skipped before the conversation starts (nothing to disambiguate) and while
     * an assistant turn has unresolved tool calls, where inserting a user message
     * would break tool_use/tool_result pairing.
     */
    private appendModelSwitchNote;
    compact(existingCredentials?: {
        accessToken: string;
        accountId?: string;
        projectId?: string;
        baseUrl?: string;
    }): Promise<void>;
    newSession(preserveConversation?: boolean): Promise<void>;
    loadSession(sessionPath: string): Promise<void>;
    /**
     * Create a branch at a specific point in the conversation.
     * Rewinds the message history to the given entry and sets the leaf
     * so new messages fork from that point.
     *
     * @param stepsBack Number of messages to rewind (default: 2 — backs up past last assistant + tool)
     */
    branch(stepsBack?: number): Promise<{
        branchedFrom: number;
        messagesKept: number;
    }>;
    /**
     * List all branches in the current session.
     */
    listBranches(): Promise<BranchInfo[]>;
    getState(): AgentSessionState;
    getPlanMode(): boolean;
    /**
     * Suppress only the pre-final Ideal self-review for this live session.
     * Autopilot uses this while Ken independently owns verification; loop-break
     * and post-compaction re-grounding remain active.
     */
    setIdealReviewSuppressed(suppressed: boolean): void;
    /** Queue a user message (optionally with attachments) to be injected mid-run
     *  as steering. Returns the new queue length. No-op semantics are the caller's
     *  concern. */
    queueMessage(text: string, attachments?: SessionAttachment[]): number;
    /** Pending queued messages (id + text), oldest first, for client display. */
    listQueuedMessages(): Array<{
        id: string;
        text: string;
    }>;
    /** Cancel one pending message by id. Returns true if it was still queued.
     *  A false return is the normal race rather than an error: the message drained
     *  into the run between the client rendering the cancel affordance and the
     *  click arriving. */
    cancelQueuedMessage(id: string): boolean;
    /** Number of messages currently queued. */
    getQueuedCount(): number;
    /** Remove and return the oldest queued message (text + attachments), or null.
     *  Used by the sidecar to run a message that queued while autopilot was
     *  reviewing (no run in flight to steer it into) — unlike {@link drainQueue},
     *  attachments survive so queued media isn't silently dropped. */
    takeNextQueuedMessage(): {
        text: string;
        attachments: SessionAttachment[];
    } | null;
    /** Clear the queue, returning the combined text (to restore to the composer).
     *  Queued attachments are dropped on cancel — the composer only restores text. */
    drainQueue(): string;
    /** Snapshot of background processes (bash run_in_background), newest-state. */
    listBackgroundProcesses(): BackgroundProcess[];
    /** Stop a background process by id. Returns a human-readable status string. */
    killBackgroundProcess(id: string): Promise<string>;
    /** Replace a host-owned system prompt in place without resetting conversation history. */
    setCustomSystemPrompt(systemPrompt: string, promptCacheKeyPrefix?: string): void;
    /**
     * Toggle plan mode: flips the shared ref (so tools enforce read-only
     * restrictions) and rebuilds the system prompt in place so the model is told
     * about the mode change on its next turn. No-op when a custom system prompt
     * is in force (the host owns the prompt then).
     */
    setPlanMode(active: boolean): Promise<void>;
    /**
     * Bake an approved plan into the system prompt so the model is told to emit
     * `[DONE:n]` markers as it completes each step (the contract the UI's
     * plan-progress widget reads). Pass `undefined` to clear it. No-op when a
     * custom system prompt is in force (the host owns the prompt then).
     */
    setApprovedPlan(approvedPlanPath: string | undefined): Promise<void>;
    /** Extra workspace roots added with `/add-dir`, in the order added. */
    getAdditionalRoots(): string[];
    /**
     * Add another workspace root. Tools already accept absolute paths, so this
     * only widens the write guard and tells the model the root exists. Rebuilding
     * the system prompt costs one cache-miss turn — the alternative (an uncached
     * suffix) would drift from the tool behaviour it describes.
     *
     * @returns the resolved root, or an error message for the user.
     */
    addDirectory(dir: string): Promise<{
        ok: true;
        root: string;
    } | {
        ok: false;
        error: string;
    }>;
    /** Remove an exact root previously added with `/add-dir`. */
    removeDirectory(dir: string): Promise<{
        ok: true;
        root: string;
    } | {
        ok: false;
        error: string;
    }>;
    /** Environment facts that vary per session rather than per host. */
    private promptEnvironment;
    /** Rebuild messages[0] from current plan-mode + approved-plan state. */
    private rebuildSystemPromptInPlace;
    /**
     * Compose the system message: stable prefix, then everything volatile behind
     * the `<!-- uncached -->` marker that providers split on for cache control.
     *
     * Anything that varies with the live model/provider/thinking level belongs in
     * the tail. Putting it in the prefix means every model switch rewrites cached
     * bytes and the next turn pays a full cache write instead of a read.
     */
    private withSystemPromptTail;
    /**
     * Sol/Terra async-orchestration guidance for the CURRENT model and thinking
     * level. Per-switch volatile by definition, so it is rendered as a tail part
     * rather than spliced into the cached prefix.
     */
    private orchestrationPolicyTail;
    /**
     * Re-render the uncached tail of messages[0] in place. The cached prefix is
     * byte-identical afterwards, so this is safe to call on every model /
     * thinking-level change.
     */
    private refreshSystemPromptTail;
    getMessages(): Message[];
    getTurnMetrics(): TurnMetricPayload[];
    private persistTurnMetric;
    private rePersistTurnMetrics;
    /** Ken Kai (mentor) turns recorded against this session, in record order. Used
     *  by the host to interleave Ken's advisory exchanges back into the transcript
     *  on resume. Never part of the LLM message history. */
    getKenTurns(): KenTurnPayload[];
    /** Autopilot verdict markers recorded against this session, in record order.
     *  Used by the host to interleave the auto-review loop's markers back into
     *  the transcript on resume, mirroring `getKenTurns`. */
    getAutopilotMarkers(): AutopilotMarkerPayload[];
    /** Non-system messages that are actually on disk. Transcript markers anchor
     *  against this (not the in-memory list, which can run ahead after a failed
     *  run), so hosts computing marker-derived values must use the same base. */
    getPersistedTranscriptCount(): number;
    /**
     * Rebase every transcript anchor (Ken turns, autopilot verdicts, app markers)
     * onto a freshly compacted message list. Called right after `this.messages`
     * is replaced and before the markers are re-persisted into the continuation
     * file, so the new file carries positions that match its own transcript.
     */
    private remapMarkerAnchors;
    /**
     * Record one Ken Kai (mentor agent) turn against this build session: the
     * user's question + Ken's reply. Kept in memory for the live transcript and
     * persisted as a `custom` entry (parentId null, so it's never on the message
     * DAG and never seen by the LLM, and can't race the build session's leaf while
     * Ken runs concurrently). `afterMessageCount` anchors it among the messages so
     * the host can interleave it chronologically. No-op persistence for transient
     * sessions (kept in memory only). Best-effort: a write failure is swallowed by
     * appendEntry's own handling.
     */
    persistKenTurn(question: string, reply: string): Promise<void>;
    /** Re-append the in-memory Ken turns to the current session file. Called after
     *  a continuation/compaction file is created so Ken's advisory history isn't
     *  lost when the session is rewritten (those rewrites only re-persist
     *  messages). Each turn keeps its original `afterMessageCount` anchor. */
    private rePersistKenTurns;
    /**
     * Record one autopilot verdict marker (prompted / done / human / capped)
     * against this build session. Kept in memory for the live transcript and
     * persisted as a `custom` entry (parentId null, same as Ken turns) so a
     * resumed session renders the exact same Ken bubble the live run showed
     * instead of dropping the marker or falling back to a raw verdict string.
     * No-op persistence for transient sessions (kept in memory only).
     */
    persistAutopilotMarker(phase: AutopilotMarkerPayload["phase"], extra?: {
        reason?: string;
        body?: string;
    }): Promise<void>;
    /** Re-append the in-memory autopilot markers to the current session file.
     *  Mirrors `rePersistKenTurns` — called after a continuation/compaction file
     *  is created so the auto-review history survives the rewrite. */
    private rePersistAutopilotMarkers;
    /** App transcript markers recorded against this session, in record order.
     *  Used by the host to interleave display-only rows (plan banner, task
     *  header, errors, user-bubble hints) back into the transcript on resume. */
    getAppMarkers(): AppMarkerPayload[];
    /**
     * Record one app transcript marker (display-only row) against this session.
     * Same treatment as autopilot markers: kept in memory for the live
     * transcript, persisted as a `custom` entry (parentId null, never on the
     * message DAG) so a resumed session shows the identical row. `anchorOffset`
     * shifts the recorded `afterMessageCount` — pass +1 for a marker that should
     * attach to the user message about to be pushed by the imminent prompt.
     * No-op persistence for transient sessions.
     */
    persistAppMarker(kind: AppMarkerPayload["kind"], data: Record<string, unknown>, anchorOffset?: number): Promise<void>;
    /** Re-append the in-memory app markers to the current session file. Mirrors
     *  `rePersistKenTurns` — called after a continuation/compaction file is
     *  created so display-only rows survive the rewrite. */
    private rePersistAppMarkers;
    /**
     * Rewrite a draft prompt into a tighter, terminology-correct version using
     * the ACTIVE provider/model. A stateless one-off LLM call (no agent loop, no
     * tools, no session mutation) — safe to run even mid-run. Returns the plain
     * enhanced text plus typed segments marking each corrected term. Errors throw
     * so the caller can surface them.
     */
    enhancePrompt(text: string): Promise<EnhanceResult>;
    /** Current reasoning/thinking level, or undefined when thinking is off. */
    getThinkingLevel(): ThinkingLevel | undefined;
    /** Set the reasoning/thinking level (undefined turns thinking off). Takes
     * effect on the next prompt, since the in-flight loop reads it at start. */
    setThinkingLevel(level: ThinkingLevel | undefined): void;
    /** Replace the abort signal (e.g. after cancellation). */
    setSignal(signal: AbortSignal): void;
    private bindManagerCancellation;
    /** True when speedProfile is "optimized" (1-h cache TTL + pre-warm), or the
     *  session was constructed with `forceLongCacheRetention` (Ken sessions). */
    private isSpeedOptimized;
    /**
     * Ordered auth-storage keys the current (provider, model) pair tries, first
     * match wins. Almost always just the provider id; Xiaomi models can prefer
     * one endpoint and fall back to another the user configured instead (e.g.
     * `mimo-v2.5-pro` prefers the Token Plan, falls back to API Credits; the
     * API-only `mimo-v2.5-pro-ultraspeed` has no fallback).
     */
    private currentAuthStorageKeys;
    private getPromptCacheKey;
    /** Stable cache-routing key for downstream sub-agent processes. */
    getCurrentCacheKey(): string | undefined;
    dispose(): Promise<void>;
    private setSessionPath;
    private createNewSession;
    private loadExistingSession;
    private prepareDynamicContext;
    private persistMessage;
    private createSlashCommandContext;
}
//# sourceMappingURL=agent-session.d.ts.map