/**
 * Unified Agent Runner — the single entry point for all agent execution.
 *
 * All surfaces (CLI, Gateway/Glass UI, channel dispatch) call runAgentTurn()
 * to execute an agent turn.  Internally adapts the clean AgentTurnParams
 * interface to the existing runEmbeddedPiAgent() pipeline, which handles
 * session management, model fallback, system prompt building, etc.
 *
 * Design principles (from agent-zero):
 * - Single execution path for all surfaces
 * - Streaming determined by callback presence, not separate code paths
 * - Clean interface hiding internal complexity
 *
 * @module
 */
import type { ImageContent } from "@mariozechner/pi-ai";
import type { ReasoningLevel, ThinkLevel, VerboseLevel } from "../auto-reply/thinking.js";
import type { AgentStreamParams } from "../commands/agent/types.js";
import type { SymiConfig } from "../config/config.js";
import type { ModelProfile } from "../config/model-profiles.js";
import { type OutboundFilterAction, type OutboundFilterReason } from "../gateway/outbound-filter.js";
import type { ExecElevatedDefaults, ExecToolDefaults } from "./bash-tools.exec-types.js";
import type { BlockReplyChunking } from "./pi-embedded-block-chunker.js";
import type { BlockReplyPayload } from "./pi-embedded-payloads.js";
import type { ClientToolDefinition } from "./pi-embedded-runner/run/params.js";
import type { EmbeddedPiRunResult } from "./pi-embedded-runner/types.js";
import type { ToolResultFormat } from "./pi-embedded-subscribe.types.js";
import type { SkillSnapshot } from "./skills.js";
export interface AgentTurnParams {
    sessionId: string;
    sessionKey: string;
    agentId?: string;
    runId?: string;
    workspaceDir: string;
    agentDir?: string;
    config: SymiConfig;
    skillsSnapshot?: SkillSnapshot;
    prompt: string;
    images?: ImageContent[];
    extraSystemPrompt?: string;
    clientTools?: ClientToolDefinition[];
    disableTools?: boolean;
    provider?: string;
    modelId?: string;
    authProfileId?: string;
    authProfileIdSource?: "auto" | "user";
    thinkLevel?: ThinkLevel;
    reasoningLevel?: ReasoningLevel;
    timeoutMs: number;
    abortSignal?: AbortSignal;
    /** Fallback models to try if primary fails. Runner handles rotation. */
    fallbackModels?: string[];
    /** Post-run hooks (verification, memory flush). Run after main turn completes. */
    postRunHooks?: PostRunHook[];
    /** Execution lane for concurrency control (e.g. "cron", "voice"). */
    lane?: string;
    /** Tool result format (markdown or plain, based on channel). */
    toolResultFormat?: ToolResultFormat;
    /** Verbose level for logging/diagnostics. */
    verboseLevel?: VerboseLevel;
    /** Owner phone numbers for owner-only tools. */
    ownerNumbers?: string[];
    /** Enforce final tag on reasoning output. */
    enforceFinalTag?: boolean;
    /** Exec tool overrides (host, security, ask, node). */
    execOverrides?: Pick<ExecToolDefaults, "host" | "security" | "ask" | "node">;
    /** Bash elevated mode defaults. */
    bashElevated?: ExecElevatedDefaults;
    /** Suppress tool error warning payloads. */
    suppressToolErrorWarnings?: boolean;
    /** Provider stream params override (temperature, maxTokens). */
    streamParams?: AgentStreamParams;
    /** Block reply break mode (text_end or message_end). */
    blockReplyBreak?: "text_end" | "message_end";
    /** Block reply chunking configuration. */
    blockReplyChunking?: BlockReplyChunking;
    /** Require explicit message tool targets (no implicit sends). */
    requireExplicitMessageTarget?: boolean;
    /** Omit the message tool from the tool list. */
    disableMessageTool?: boolean;
    /** Symipulse inactivity timeout in milliseconds. */
    symipulseMs?: number;
    /** Retry once on transient HTTP errors (502/521) with 2.5s delay. */
    retryOnTransientError?: boolean;
    channel?: ChannelContext;
    callbacks?: AgentTurnCallbacks;
}
export interface ChannelContext {
    messageChannel?: string;
    messageProvider?: string;
    agentAccountId?: string;
    messageTo?: string;
    messageThreadId?: string | number;
    groupId?: string | null;
    groupChannel?: string | null;
    groupSpace?: string | null;
    spawnedBy?: string | null;
    senderId?: string | null;
    senderName?: string | null;
    senderUsername?: string | null;
    senderE164?: string | null;
    senderIsOwner?: boolean;
    currentChannelId?: string;
    currentThreadTs?: string;
    replyToMode?: "off" | "first" | "all";
    hasRepliedRef?: {
        value: boolean;
    };
}
export interface AgentTurnCallbacks {
    /** Streaming text delta. */
    onDelta?: (text: string) => void | Promise<void>;
    /** Final complete response. */
    onFinal?: (text: string, metadata: ResponseMetadata) => void | Promise<void>;
    /** Tool execution started. */
    onToolStart?: (name: string, args: Record<string, unknown>) => void | Promise<void>;
    /** Tool execution completed. */
    onToolResult?: (name: string, result: string) => void | Promise<void>;
    /** Thinking/reasoning output. */
    onThinking?: (text: string) => void | Promise<void>;
    /** Error during execution. */
    onError?: (error: Error) => void | Promise<void>;
    /** Agent lifecycle phase change. */
    onLifecycle?: (phase: "start" | "thinking" | "streaming" | "end" | "error") => void | Promise<void>;
    /** Raw agent event (for Glass UI event broadcasting). */
    onAgentEvent?: (evt: {
        stream: string;
        data: Record<string, unknown>;
    }) => void;
    /** Block streaming: called with chunk text when a block break is reached. */
    onBlockReply?: (payload: BlockReplyPayload & {
        isFinal: boolean;
    }) => void | Promise<void>;
    /** Block streaming: flush pending buffer (e.g. before tool execution). */
    onBlockReplyFlush?: () => void | Promise<void>;
    /** Typing: signal that the agent is actively working. */
    onTypingStart?: () => void | Promise<void>;
    /** Typing: signal that the agent has paused/completed. */
    onTypingStop?: () => void | Promise<void>;
    /** Compaction: context window was compressed. */
    onCompaction?: (result: {
        tokensBefore: number;
        tokensAfter: number;
    }) => void | Promise<void>;
    /** Model fallback: primary model failed, trying fallback. */
    onFallback?: (from: string, to: string, reason: string) => void | Promise<void>;
}
export interface ResponseMetadata {
    provider: string;
    modelId: string;
    tokenCount: number;
    durationMs: number;
    toolsUsed: string[];
}
export interface AgentTurnResult {
    /**
     * Final response text after the gateway-boundary outbound filter.
     *
     * `outbound.action === "drop"` means the model produced a bare NO_REPLY
     * token (silent reply); `text` is empty and downstream surfaces should
     * suppress delivery. The unfiltered text is still available via
     * `rawResult.payloads`.
     */
    text: string;
    /**
     * Pre-filter response text — the joined assistant payloads as they
     * arrived from the model. Useful for telemetry and for callers that
     * want to inspect what would have been sent before the silent-reply
     * rules dropped it.
     */
    rawText: string;
    /**
     * Verdict from the outbound filter (lifted from gateway emitChatFinal
     * in Phase 1 of the pipeline-collapse work). Surfaces here so every
     * surface — CLI, channels, cron, gateway — applies the same rules
     * uniformly. `action: "drop"` means suppress; `action: "deliver"` and
     * `"deliver-stripped"` mean send `text` as-is.
     */
    outbound: {
        action: OutboundFilterAction;
        reason: OutboundFilterReason;
    };
    /** Duration of the agent run. */
    durationMs: number;
    /** Provider used. */
    provider: string;
    /** Model used. */
    modelId: string;
    /** Resolved model profile used for this turn. */
    profile: ModelProfile;
    /** Whether a messaging tool sent a message (suppresses duplicate delivery). */
    didSendViaMessagingTool: boolean;
    /** The raw result from the internal runner (for callers that need full detail). */
    rawResult: EmbeddedPiRunResult;
}
/**
 * Post-run hook — runs after the main agent turn completes.
 * Used for verification prompts, memory flush, and other post-processing.
 */
export interface PostRunHook {
    /** Hook name for logging. */
    name: string;
    /** Whether this hook should run given the turn result. */
    shouldRun: (result: AgentTurnResult) => boolean;
    /** The hook body — receives the turn result and original params. */
    execute: (result: AgentTurnResult, params: AgentTurnParams) => Promise<void>;
}
/**
 * Internal: a single agent turn WITHOUT the circuit-breaker recovery
 * wrapper. The exported `runAgentTurn` wraps this with
 * `withCircuitBreakerRecovery` so a tool-error breaker triggers exactly
 * one retry with tools disabled — see Phase 5 of the pipeline-collapse
 * work (src/auto-reply/reply/middleware-circuit-breaker.ts).
 *
 * Test code that needs to bypass the recovery (e.g. to assert breaker
 * results surface raw) should call this implementation directly via the
 * test-only export at the bottom of this module. Production code should
 * always go through `runAgentTurn`.
 */
declare function runAgentTurnImpl(params: AgentTurnParams): Promise<AgentTurnResult>;
/**
 * Execute a single agent turn. This is the unified entry point.
 *
 * Translates the clean AgentTurnParams interface to the internal
 * RunEmbeddedPiAgentParams and calls runEmbeddedPiAgent(). The proven
 * internals (session management, system prompt building, tool creation,
 * pi-agent-core integration) are preserved inside `runAgentTurnImpl`;
 * cross-cutting concerns (model fallback, transient retry, breaker
 * recovery) live in the middleware stack documented above.
 */
export declare function runAgentTurn(params: AgentTurnParams): Promise<AgentTurnResult>;
/** @internal — exposed for tests that need to bypass the middleware stack. */
export declare const __internal_runAgentTurnImpl: typeof runAgentTurnImpl;
export {};
