import type { AgentSignalContents, AgentSignalInput } from '../agent/signals.js';
import type { MastraBrowser } from '../browser/browser.js';
import { Mastra } from '../mastra/index.js';
import type { MastraMemory } from '../memory/memory.js';
import type { TracingContext, TracingOptions } from '../observability/index.js';
import { RequestContext } from '../request-context/index.js';
import type { ObservationalMemoryRecord } from '../storage/types.js';
import { Workspace } from '../workspace/workspace.js';
import type { TaskItemSnapshot } from './tools.js';
import type { AvailableModel, HeartbeatHandler, HarnessConfig, HarnessDisplayState, HarnessDisplayStateListener, HarnessDisplayStateSubscriptionOptions, HarnessEventListener, HarnessMessage, HarnessMode, HarnessQuestionAnswer, HarnessSession, HarnessThread, ModelAuthStatus, PermissionPolicy, PermissionRules, TokenUsage, ToolCategory } from './types.js';
/**
 * The Harness orchestrates multiple agent modes, shared state, memory, and storage.
 * It's the core abstraction that a TUI (or other UI) controls.
 *
 * @example
 * ```ts
 * const harness = new Harness({
 *   id: "my-coding-agent",
 *   storage: new LibSQLStore({ url: "file:./data.db" }),
 *   stateSchema: z.object({
 *     currentModelId: z.string().optional(),
 *   }),
 *   modes: [
 *     { id: "plan", name: "Plan", default: true, agent: planAgent },
 *     { id: "build", name: "Build", agent: buildAgent },
 *   ],
 * })
 *
 * harness.subscribe((event) => {
 *   if (event.type === "message_update") renderMessage(event.message)
 * })
 *
 * await harness.init()
 * await harness.sendMessage({ content: "Hello!" })
 * ```
 */
export declare class Harness<TState = {}> {
    #private;
    readonly id: string;
    private config;
    private stateSchema;
    private state;
    private currentModeId;
    private currentThreadId;
    private resourceId;
    private defaultResourceId;
    private listeners;
    private displayStateSchedulers;
    private abortController;
    private abortRequested;
    private currentRunId;
    private currentTraceId;
    private currentOperationId;
    private agentThreadSubscription;
    private agentThreadSubscriptionKey;
    private followUpQueue;
    private pendingApprovalResolve;
    private pendingApprovalToolName;
    private pendingSuspensionRunId;
    private pendingSuspensionToolCallId;
    private pendingQuestions;
    private pendingPlanApprovals;
    private workspace;
    private workspaceFn;
    private workspaceInitialized;
    private browser;
    private browserFn;
    private heartbeatTimers;
    private tokenUsage;
    private sessionGrantedCategories;
    private sessionGrantedTools;
    private displayState;
    private stateUpdateQueue;
    constructor(config: HarnessConfig<TState>);
    /**
     * Access the internal Mastra instance.
     * Available after `init()` when storage is configured.
     * Useful for scorer registration, observability access, and eval tooling.
     */
    getMastra(): Mastra | undefined;
    /**
     * Sets or updates the harness-level browser and propagates it to static mode agents.
     */
    setBrowser(browser: MastraBrowser | undefined): void;
    /**
     * Initialize the harness — loads storage and workspace.
     * Must be called before using the harness.
     */
    init(): Promise<void>;
    /**
     * Select the most recent thread, or create one if none exist.
     */
    selectOrCreateThread(): Promise<HarnessThread>;
    private getMemoryStorage;
    /**
     * Get current harness state (read-only snapshot).
     */
    getState(): Readonly<TState>;
    private applyStateUpdates;
    /**
     * Update harness state. Validates against schema if provided.
     * Emits state_changed event.
     */
    setState(updates: Partial<TState>): Promise<void>;
    private updateState;
    private getSchemaDefaults;
    listModes(): HarnessMode<TState>[];
    getCurrentModeId(): string;
    getCurrentMode(): HarnessMode<TState>;
    /**
     * Switch to a different mode.
     * Aborts any in-progress generation and switches to the mode's default model.
     */
    switchMode({ modeId }: {
        modeId: string;
    }): Promise<void>;
    /**
     * Load the stored model ID for a specific mode.
     * Falls back to: thread metadata -> mode's defaultModelId -> current model.
     */
    private loadModeModelId;
    private propagateRuntimeServicesToAgent;
    /**
     * Get the agent for the current mode.
     */
    private getCurrentAgent;
    /**
     * Get a short display name from the current model ID.
     */
    getModelName(): string;
    /**
     * Get the full model ID (e.g., "anthropic/claude-sonnet-4").
     */
    getFullModelId(): string;
    /**
     * Switch to a different model at runtime.
     */
    switchModel({ modelId, scope, modeId, }: {
        modelId: string;
        scope?: 'global' | 'thread';
        modeId?: string;
    }): Promise<void>;
    getCurrentModelId(): string;
    hasModelSelected(): boolean;
    /**
     * Check if the current model's provider has authentication configured.
     * Uses the provider registry's `apiKeyEnvVar` and the optional `modelAuthChecker` hook.
     */
    getCurrentModelAuthStatus(): Promise<ModelAuthStatus>;
    /**
     * Get all available models from the provider registry with auth status.
     * Uses the optional `modelAuthChecker`, `modelUseCountProvider`, and
     * `customModelCatalogProvider` hooks.
     */
    listAvailableModels(): Promise<AvailableModel[]>;
    private getProviderApiKeyEnvVar;
    getCurrentThreadId(): string | null;
    getResourceId(): string;
    getResolvedMemory(): Promise<MastraMemory | null>;
    setResourceId({ resourceId }: {
        resourceId: string;
    }): void;
    getDefaultResourceId(): string;
    getKnownResourceIds(): Promise<string[]>;
    createThread({ title }?: {
        title?: string;
    }): Promise<HarnessThread>;
    /**
     * Returns a memory accessor with thread and message management methods.
     */
    get memory(): {
        createThread: ({ title }?: {
            title?: string;
        }) => Promise<HarnessThread>;
        switchThread: ({ threadId }: {
            threadId: string;
        }) => Promise<void>;
        listThreads: (options?: {
            allResources?: boolean;
            /**
             * Include forked subagent fork threads. Defaults to false: forks are
             * transient clones used by the runtime and should not show up in user-facing
             * thread lists / pickers / startup flows. Set to true for admin / debug
             * tooling that needs to see every thread.
             */
            includeForkedSubagents?: boolean;
        }) => Promise<HarnessThread[]>;
        renameThread: ({ title }: {
            title: string;
        }) => Promise<void>;
        deleteThread: ({ threadId }: {
            threadId: string;
        }) => Promise<void>;
    };
    private deleteThread;
    renameThread({ title }: {
        title: string;
    }): Promise<void>;
    cloneThread({ sourceThreadId, title, resourceId, }?: {
        sourceThreadId?: string;
        title?: string;
        resourceId?: string;
    }): Promise<HarnessThread>;
    switchThread({ threadId }: {
        threadId: string;
    }): Promise<void>;
    listThreads(options?: {
        allResources?: boolean;
        /**
         * Include forked subagent fork threads. Defaults to false: forks are
         * transient clones used by the runtime and should not show up in user-facing
         * thread lists / pickers / startup flows. Set to true for admin / debug
         * tooling that needs to see every thread.
         */
        includeForkedSubagents?: boolean;
    }): Promise<HarnessThread[]>;
    setThreadSetting({ key, value }: {
        key: string;
        value: unknown;
    }): Promise<void>;
    private deleteThreadSetting;
    private loadThreadMetadata;
    /**
     * Load observational memory progress for the current thread.
     * Reads the OM record and recent messages to reconstruct status,
     * then emits an `om_status` event for the UI.
     */
    loadOMProgress(): Promise<void>;
    getObservationalMemoryRecord(): Promise<ObservationalMemoryRecord | null>;
    /**
     * Returns the observer model ID from state, falling back to omConfig defaults.
     */
    getObserverModelId(): string | undefined;
    /**
     * Returns the reflector model ID from state, falling back to omConfig defaults.
     */
    getReflectorModelId(): string | undefined;
    /**
     * Returns the observation threshold from state, falling back to omConfig defaults.
     */
    getObservationThreshold(): number | undefined;
    /**
     * Returns the reflection threshold from state, falling back to omConfig defaults.
     */
    getReflectionThreshold(): number | undefined;
    /**
     * Resolves the observer model ID to a language model instance via `resolveModel`.
     */
    getResolvedObserverModel(): import("../memory").MastraLanguageModel | undefined;
    /**
     * Resolves the reflector model ID to a language model instance via `resolveModel`.
     */
    getResolvedReflectorModel(): import("../memory").MastraLanguageModel | undefined;
    /**
     * Switch the Observer model.
     */
    switchObserverModel({ modelId }: {
        modelId: string;
    }): Promise<void>;
    /**
     * Switch the Reflector model.
     */
    switchReflectorModel({ modelId }: {
        modelId: string;
    }): Promise<void>;
    getSubagentModelId({ agentType }?: {
        agentType?: string;
    }): string | null;
    setSubagentModelId({ modelId, agentType }: {
        modelId: string;
        agentType?: string;
    }): Promise<void>;
    grantSessionCategory({ category }: {
        category: ToolCategory;
    }): void;
    grantSessionTool({ toolName }: {
        toolName: string;
    }): void;
    getSessionGrants(): {
        categories: ToolCategory[];
        tools: string[];
    };
    getToolCategory({ toolName }: {
        toolName: string;
    }): ToolCategory | null;
    setPermissionForCategory({ category, policy }: {
        category: ToolCategory;
        policy: PermissionPolicy;
    }): void;
    setPermissionForTool({ toolName, policy }: {
        toolName: string;
        policy: PermissionPolicy;
    }): void;
    getPermissionRules(): PermissionRules;
    /**
     * Resolve whether a tool call should be auto-approved, denied, or asked.
     * Resolution chain: per-tool deny → yolo → per-tool policy → session tool grant →
     * session category grant → category policy → "ask"
     */
    private resolveToolApproval;
    private cleanupAgentThreadSubscription;
    private getAgentThreadSubscriptionKey;
    private ensureAgentThreadSubscription;
    private ensureCurrentAgentThreadSubscription;
    private drainFollowUpQueue;
    private isActiveAgentThreadSubscription;
    private finishSubscribedStreamRun;
    private handleSubscribedStreamError;
    private processSubscribedThreadStream;
    /**
     * Send a signal to the current agent/thread.
     */
    sendSignal(input: AgentSignalInput | {
        content: AgentSignalContents;
        tracingContext?: TracingContext;
        tracingOptions?: TracingOptions;
        requestContext?: RequestContext;
    }): {
        id: string;
        type: AgentSignalInput['type'];
        accepted: Promise<{
            accepted: true;
            runId: string;
        }>;
    };
    /**
     * Send a message to the current agent.
     * Streams the response and emits events.
     */
    sendMessage({ content, files, tracingContext, tracingOptions, requestContext: requestContextInput, }: {
        content: string;
        files?: Array<{
            data: string;
            mediaType: string;
            filename?: string;
        }>;
        tracingContext?: TracingContext;
        tracingOptions?: TracingOptions;
        requestContext?: RequestContext;
    }): Promise<void>;
    listMessages(options?: {
        limit?: number;
    }): Promise<HarnessMessage[]>;
    saveSystemReminderMessage({ message, reminderType, role, metadata, }: {
        message: string;
        reminderType: string;
        role?: 'user' | 'assistant' | 'system';
        metadata?: Record<string, unknown>;
    }): Promise<HarnessMessage | null>;
    listMessagesForThread({ threadId, limit }: {
        threadId: string;
        limit?: number;
    }): Promise<HarnessMessage[]>;
    getFirstUserMessageForThread({ threadId }: {
        threadId: string;
    }): Promise<HarnessMessage | null>;
    getFirstUserMessagesForThreads({ threadIds }: {
        threadIds: string[];
    }): Promise<Map<string, HarnessMessage>>;
    private convertToHarnessMessage;
    /**
     * Process a stream response (shared between sendMessage and tool approval).
     */
    private createStreamState;
    private abortForOmFailure;
    private processStream;
    private processStreamChunk;
    private finishStreamState;
    /**
     * Abort the current operation.
     */
    abort(): void;
    /**
     * Steer the agent mid-stream: aborts current run and sends a new message.
     */
    steer({ content, requestContext }: {
        content: string;
        requestContext?: RequestContext;
    }): Promise<void>;
    /**
     * Queue a follow-up message to be processed after the current operation completes.
     */
    followUp({ content, requestContext }: {
        content: string;
        requestContext?: RequestContext;
    }): Promise<void>;
    getFollowUpCount(): number;
    isRunning(): boolean;
    getCurrentRunId(): string | null;
    isCurrentThreadStreamActive(): boolean;
    /**
     * Resolve once the current thread's stream is fully idle.
     *
     * After `abort()` is called the run's status can still be `'running'` for a
     * few microtasks while the underlying model stream finalizes. Callers that
     * need to send a fresh signal after an abort (e.g. plan approval → mode
     * switch → trigger reminder) should await this before calling `sendSignal`
     * to avoid the new signal being queued onto the dying run, which would then
     * be drained with the previous run's already-aborted abortSignal.
     */
    private waitForCurrentThreadStreamIdle;
    getCurrentTraceId(): string | null;
    private getSubagentDisplayName;
    /**
     * Returns a read-only snapshot of the canonical display state.
     * UIs should use this to render instead of building up state from raw events.
     */
    getDisplayState(): Readonly<HarnessDisplayState>;
    /**
     * Restore task display state after a UI replays persisted task tool history.
     * This updates the Harness-owned display snapshot without emitting a live
     * `task_updated` event, since no task tool just ran.
     */
    restoreDisplayTasks(tasks: TaskItemSnapshot[]): void;
    /**
     * Reset display state fields that are scoped to a thread.
     * Called on thread switch/creation.
     */
    private resetThreadDisplayState;
    /**
     * Respond to a pending tool approval from the UI.
     * "always_allow_category" grants the tool's category for the rest of the session, then approves.
     */
    respondToToolApproval({ decision, requestContext, }: {
        decision: 'approve' | 'decline' | 'always_allow_category';
        requestContext?: RequestContext;
    }): void;
    /**
     * Respond to a pending tool suspension from the UI.
     * Provides resume data so the suspended tool can continue execution.
     */
    respondToToolSuspension({ resumeData, requestContext, }: {
        resumeData: any;
        requestContext?: RequestContext;
    }): Promise<void>;
    /**
     * Register a pending question resolver.
     * Called by agent tools (e.g., ask_user) to pause execution until the UI responds.
     */
    registerQuestion({ questionId, resolve, }: {
        questionId: string;
        resolve: (answer: HarnessQuestionAnswer) => void;
    }): void;
    /**
     * Resolve a pending question with the user's answer.
     * Called by the UI when the user responds to a question dialog.
     */
    respondToQuestion({ questionId, answer }: {
        questionId: string;
        answer: HarnessQuestionAnswer;
    }): void;
    /**
     * Register a pending plan approval resolver.
     * Called by agent tools (e.g., submit_plan) to pause execution until approval.
     */
    registerPlanApproval({ planId, resolve, }: {
        planId: string;
        resolve: (result: {
            action: 'approved' | 'rejected';
            feedback?: string;
        }) => void;
    }): void;
    /**
     * Respond to a pending plan approval.
     * On approval: resolves the suspended plan tool, then switches to the default mode.
     * On rejection: resolves with feedback (stays in current mode).
     */
    respondToPlanApproval({ planId, response, }: {
        planId: string;
        response: {
            action: 'approved' | 'rejected';
            feedback?: string;
        };
    }): Promise<void>;
    private handleToolApprove;
    private handleToolDecline;
    private handleToolResume;
    /**
     * Subscribe to harness events. Returns an unsubscribe function.
     */
    subscribe(listener: HarnessEventListener): () => void;
    /**
     * Subscribe to coalesced display state snapshots.
     *
     * Use this for UI rendering paths that only need the latest display state.
     * Raw event consumers should continue to use `subscribe()`.
     */
    subscribeDisplayState(listener: HarnessDisplayStateListener, options?: HarnessDisplayStateSubscriptionOptions): () => void;
    private emit;
    private dispatchDisplayStateChanged;
    private dispatchToListeners;
    /**
     * Apply a display state update based on an incoming event.
     * This is the centralized state machine that keeps HarnessDisplayState in sync
     * with every event the Harness emits.
     */
    private applyDisplayStateUpdate;
    /**
     * Build the toolsets object that includes built-in harness tools (ask_user, submit_plan,
     * and optionally subagent) plus any user-configured tools.
     * Used by sendMessage, handleToolApprove, and handleToolDecline.
     */
    private buildToolsets;
    /**
     * Build request context for agent execution.
     * Tools can access harness state via requestContext.get('harness').
     */
    private buildRequestContext;
    /**
     * Resolve memory from config — handles both static instances and dynamic factory functions.
     */
    private resolveMemory;
    getTokenUsage(): TokenUsage;
    private persistTokenUsage;
    getWorkspace(): Workspace | undefined;
    /**
     * Eagerly resolve the workspace. For dynamic workspaces (factory function),
     * this triggers resolution and caches the result so getWorkspace() returns it.
     * Useful for code paths outside the request flow (e.g. slash commands).
     */
    resolveWorkspace({ requestContext, }?: {
        requestContext?: RequestContext;
    }): Promise<Workspace | undefined>;
    hasWorkspace(): boolean;
    isWorkspaceReady(): boolean;
    destroyWorkspace(): Promise<void>;
    private startHeartbeats;
    registerHeartbeat(handler: HeartbeatHandler): void;
    removeHeartbeat({ id }: {
        id: string;
    }): Promise<void>;
    stopHeartbeats(): Promise<void>;
    destroy(): Promise<void>;
    getSession(): Promise<HarnessSession>;
    private generateId;
}
//# sourceMappingURL=harness.d.ts.map