import { z } from 'zod';

/**
 * MemoryRef — opaque typed reference for resumable agent context.
 *
 * The ref itself is a lightweight pointer; the actual memory content
 * is managed by the MemoryStore or held server-side by the provider.
 */
interface MemoryRef {
    /** Opaque identifier (e.g. session UUID, response ID, agent ID). */
    id: string;
    /** Provider that generated this ref (e.g. "claude-agent-sdk", "openai-responses"). */
    provider: string;
    /** Compatibility tag for format validation across versions. */
    compat: string;
    /** ISO 8601 timestamp of ref creation. */
    created_at: string;
    /** ID of the run that produced this ref, for chain tracking. */
    parent_run_id?: string;
}
/**
 * Pluggable store for memory content that backs MemoryRef pointers.
 *
 * Adapters that use server-side state (OpenAI, Gemini) may not need
 * the store — the ref ID alone is sufficient for resume. Adapters
 * with local state (Claude transcript, Gemini chat history) use the
 * store to persist and retrieve content.
 */
interface MemoryStore {
    save(ref: MemoryRef, content: unknown): Promise<void>;
    load(ref: MemoryRef): Promise<unknown | null>;
    delete(ref: MemoryRef): Promise<void>;
}
/**
 * In-memory store for testing. State is lost when the process exits.
 */
declare class InMemoryStore implements MemoryStore {
    private data;
    save(ref: MemoryRef, content: unknown): Promise<void>;
    load(ref: MemoryRef): Promise<unknown | null>;
    delete(ref: MemoryRef): Promise<void>;
}

/**
 * Candidate Agents — backend-neutral bridge for LLM-internal routing (model B)
 *
 * The runtime registers a set of *candidate sub-agents* with the SDK so the
 * entry/main agent's LLM can delegate to them internally via the SDK's native
 * subagent mechanism:
 *
 *   - Claude  `Options.agents: Record<string, AgentDefinition>`
 *   - OpenAI  `Agent.handoffs: Agent[]`
 *   - ADK     `LlmAgent.subAgents: BaseAgent[]`
 *
 * `CandidateAgent` is the common, SDK-independent contract. Each adapter maps it
 * onto its provider's native shape. The selection rule (which agents become
 * candidates) lives here so all adapters stay backend-agnostic.
 */

/**
 * SDK-independent description of a sub-agent the entry agent's LLM may delegate
 * to. Adapters translate this into their provider's native subagent shape.
 */
interface CandidateAgent {
    /** Agent id (used as the SDK subagent key / name). */
    name: string;
    /** When to use this agent — the routing hint shown to the delegating LLM. */
    description: string;
    /** The agent's system prompt (role / purpose / responsibilities / constraints / rules). */
    prompt: string;
    /** Optional allowed tool names (omit to inherit from the parent agent). */
    tools?: string[];
    /** Optional model id (omit to inherit from the parent agent). */
    model?: string;
}
/**
 * Render an agent contract into its system-prompt string: the static
 * Role / Responsibilities / Constraints / Rules sections.
 *
 * Shared by `buildSplitTaskPrompt` (entry agent system prompt) and
 * `buildCandidateAgents` (each candidate's `prompt`) so both stay in sync.
 */
declare function renderAgentSystemPrompt(agent: AgentContractLike): string;
interface BuildCandidateAgentsOptions {
    /** The entry/main agent id. Excluded from the candidate set. */
    entryAgentId?: string;
    /**
     * When provided (typically the entry agent's `can_invoke_agents`), restrict
     * candidates to these agent ids. Omit to allow every non-entry agent.
     */
    allowedAgentIds?: readonly string[];
}
/**
 * Build the candidate sub-agent set from an agent registry.
 *
 * Selection rule: every agent EXCEPT the entry agent; if `allowedAgentIds` is
 * given, further restrict to that allow-list.
 */
declare function buildCandidateAgents(agentRegistry: Record<string, AgentContractLike>, opts?: BuildCandidateAgentsOptions): CandidateAgent[];

/**
 * Task Runner — runs a single DSL task via an SDK agent
 *
 * Responsibilities:
 *   1. Resolve task contract → target agent contract
 *   2. Build the agent prompt from contract + context
 *   3. Apply plugin prompt enhancers and beforeTask hooks
 *   4. Send to SDK agent (via abstract SdkAdapter) and stream result
 *   5. Parse + validate result against handoff schema
 *   6. Apply plugin afterTask hooks
 *   7. Return typed result or escalation signal
 *
 * Two recovery strategies:
 *   - followUp: lightweight, same session — fix output format only
 *   - retry:    heavyweight, new session — re-execute entire task
 */

interface AgentContractLike {
    readonly id: string;
    readonly role_name: string;
    readonly purpose: string;
    readonly mode: "read-write" | "read-only";
    readonly responsibilities: readonly string[];
    readonly constraints: readonly string[];
    readonly rules?: readonly {
        readonly id: string;
        readonly description: string;
        readonly severity: string;
    }[];
    /**
     * Agent ids this agent is allowed to delegate to. When present, it restricts
     * the candidate sub-agent set registered with the SDK for LLM-internal routing.
     */
    readonly can_invoke_agents?: readonly string[];
    /**
     * Tool names this agent may execute. When present, sub-agents receive an
     * isolated tool set instead of inheriting the parent agent's tools.
     */
    readonly can_execute_tools?: readonly string[];
}
interface TaskContractLike {
    readonly id: string;
    readonly description: string;
    readonly target_agent: string;
    readonly result_handoff: string;
    readonly completion_criteria: readonly string[];
    readonly model_class?: "fast" | "standard" | "thinking";
    /**
     * When true, the adapter may enable Dynamic Workflow tools (e.g. Claude's
     * Workflow tool) so the agent can internally parallelise sub-tasks.
     * Handoff validation at the task boundary is still enforced.
     */
    readonly allow_dynamic_workflow?: boolean;
}
/**
 * Progress event emitted by adapters during agent execution.
 * Enables real-time visibility into what the agent is doing
 * (tool calls, text output, status changes).
 */
interface AgentProgressEvent {
    type: "tool_use" | "tool_result" | "text" | "status" | "cache_metrics";
    tool_name?: string;
    /** Tool invocation arguments (e.g. file path, command). */
    input?: Record<string, unknown>;
    message?: string;
    /** SDK session ID for correlating events within a single adapter call. */
    session_id?: string;
    /** Cache utilization metrics from the SDK response. */
    cacheMetrics?: {
        cachedInputTokens?: number;
        totalInputTokens?: number;
    };
}
/**
 * A prompt split into static (cacheable) and dynamic (per-invocation) sections.
 * Adapters that support prompt caching can use the `system` sections as
 * provider-specific system prompts, reducing token costs on repeated calls.
 */
interface SplitPrompt {
    /** Static sections: role, responsibilities, constraints, rules, task, schema, recovery. */
    system: string[];
    /** Dynamic sections: user request, handoff input, prior context, files, acceptance criteria. */
    user: string;
}
/**
 * Optional cache configuration for adapters that support prompt caching.
 * Provider-specific defaults apply when individual fields are omitted.
 */
interface CacheConfig {
    /** Enable prompt caching. Defaults to true when the adapter supports it. */
    enabled?: boolean;
    /** Provider-specific TTL (e.g. "5m", "1h", "24h"). */
    ttl?: string;
    /** Stable key for cross-session cache reuse (provider-specific). */
    cacheKey?: string;
}
/**
 * Base options for SdkAdapter.send(). SDK-specific options (model, cwd,
 * sessionMode, etc.) belong on the adapter constructor / factory — not here.
 */
interface AdapterSendOptions {
    readonly: boolean;
    /**
     * Optional callback invoked with intermediate progress events during execution.
     * Adapters that consume an internal event stream (e.g. Claude SDK's AsyncGenerator)
     * call this for each non-result message, enabling callers to display live progress.
     */
    onProgress?: (event: AgentProgressEvent) => void;
    /**
     * Split prompt for prompt caching support. When provided, adapters that support
     * caching can separate static (cacheable) instructions from dynamic content.
     * Adapters without caching support can ignore this and use the prompt argument.
     */
    splitPrompt?: SplitPrompt;
    /**
     * Candidate sub-agents the entry agent's LLM may delegate to (model B,
     * LLM-internal routing). Adapters register these via their native subagent
     * mechanism (Claude `agents`, OpenAI `handoffs`, ADK `subAgents`). When
     * omitted or empty, adapters behave exactly as before (single agent).
     */
    agents?: CandidateAgent[];
    /**
     * When true, adapters that support dynamic workflow tools (e.g. Claude's
     * Workflow tool for agent()/pipeline()/parallel()) should enable them.
     * The task's final output is still validated against the handoff schema.
     */
    allowDynamicWorkflow?: boolean;
}
/**
 * Rich execution request for adapters that need more than a prompt string.
 * Adapters can implement sendExecution() to receive full contract context.
 */
interface AgentExecutionRequest {
    agentId: string;
    taskId: string;
    prompt: string;
    handoff?: {
        type: string;
        payload: unknown;
    };
    schema?: {
        handoffType: string;
        zodSchema: unknown;
        promptDescription: string;
    };
    context: TaskContext;
    /** Resumable memory reference from a previous run. */
    memoryRef?: MemoryRef;
    /**
     * Split prompt for prompt caching support. When provided, adapters can
     * separate static instructions (system) from dynamic content (user).
     */
    splitPrompt?: SplitPrompt;
    /**
     * Candidate sub-agents for LLM-internal routing (model B). Mirrors
     * `AdapterSendOptions.agents`; also forwarded via `options.agents`.
     */
    agents?: CandidateAgent[];
    options: AdapterSendOptions & {
        maxFollowUps: number;
        attempt: number;
    };
}
interface SdkAdapter {
    /** Start a new task session and return the full text response. */
    send(prompt: string, options: AdapterSendOptions): Promise<string>;
    /**
     * Send a follow-up message within the same agent session.
     * Used for output-format corrections without re-executing the task.
     * Falls back to send() if not implemented (stateless adapters like mock).
     */
    followUp?(message: string): Promise<string>;
    /**
     * Rich execution path. When implemented, the runtime prefers this over
     * send() and passes the full contract context. Adapters that only need
     * a prompt string can ignore this — the runtime falls back to send().
     */
    sendExecution?(request: AgentExecutionRequest): Promise<string>;
    /** Return the memory_ref produced by the last send/sendExecution call. */
    getLastMemoryRef?(): MemoryRef | null;
    /** Check if this adapter is compatible with the given compat tag. */
    isCompatible?(compat: string): boolean;
}
interface TaskContext {
    user_request: string;
    prior_context?: string;
    relevant_paths?: string[];
    acceptance_criteria?: string[];
    /**
     * Structured handoff input (primary data). When present, prompt builders
     * should derive the prompt from this rather than user_request alone.
     */
    handoff_input?: {
        type: string;
        version?: number;
        payload: unknown;
    };
    /** Arbitrary structured variables plugins or workflow context may inject. */
    variables?: Record<string, unknown>;
    /** Resumable memory reference from a previous run. */
    memoryRef?: MemoryRef;
}
type TaskOutcome = {
    status: "success";
    data: unknown;
    raw: string;
    memoryRef?: MemoryRef;
} | {
    status: "validation_error";
    errors: z.ZodError;
    raw: string;
} | {
    status: "escalation";
    reason: string;
    raw: string;
} | {
    status: "error";
    message: string;
};
/**
 * Retry strategy decision.
 *
 * - "follow_up": lightweight — same session, fix output format only
 * - "retry":     heavyweight — new send(), re-execute the entire task
 * - "abort":     stop retrying, return the current outcome
 */
type RetryDecision = "follow_up" | "retry" | "abort";
interface TaskRunOptions {
    /** Max follow-up attempts (output format correction, same session). Default: 2 */
    maxFollowUps?: number;
    /** Max full retry attempts (re-execute entire task via send). Default: 0 */
    maxRetries?: number;
    /**
     * Called on each failure to decide which recovery strategy to use.
     * Default: validation_error → follow_up, empty output → retry, else abort.
     */
    decideRetryStrategy?: (outcome: TaskOutcome, counts: {
        followUps: number;
        retries: number;
    }) => Promise<RetryDecision> | RetryDecision;
    /**
     * Writable stream for real-time progress output during agent execution.
     * When provided, intermediate adapter events (tool use, status, etc.)
     * are formatted and written here. Typical value: process.stderr.
     */
    progressOutput?: {
        write(chunk: string): unknown;
    };
}
interface TaskRunResult {
    outcome: TaskOutcome;
    follow_ups_used: number;
    retries_used: number;
}
/**
 * Convert a Zod schema into a human-readable field table for inclusion in LLM prompts.
 * Recursively generates sub-tables for nested objects and array elements.
 */
declare function zodSchemaToPromptDescription(schema: z.ZodType): string;
/**
 * Generate a YAML example from a Zod schema shape, recursively expanding
 * nested objects and arrays up to a configurable depth.
 */
declare function zodSchemaToYamlExample(schema: z.ZodType, maxDepth?: number): string;
interface PromptBuilderOptions {
    handoffSchemas?: Record<string, z.ZodType>;
    retry?: {
        condition: string;
        fix_task: string;
        revalidate_task?: string;
    };
}
/**
 * Build a prompt split into static (cacheable) and dynamic (per-invocation) parts.
 *
 * Static (system): Role, Responsibilities, Constraints, Rules, Task description,
 * Completion Criteria, Output Format / Schema, Recovery Instructions.
 *
 * Dynamic (user): User Request, Handoff Input, Prior Context,
 * Relevant Files, Acceptance Criteria.
 */
declare function buildSplitTaskPrompt(agent: AgentContractLike, task: TaskContractLike, context: TaskContext, options?: PromptBuilderOptions): SplitPrompt;
declare function buildTaskPrompt(agent: AgentContractLike, task: TaskContractLike, context: TaskContext, options?: PromptBuilderOptions): string;
declare function extractStructuredResult(raw: string): unknown | null;
declare function buildRetryFollowUp(task: TaskContractLike, lastOutcome: TaskOutcome, options?: PromptBuilderOptions): string;
declare function runTask(adapter: SdkAdapter, taskId: string, context: TaskContext, options?: TaskRunOptions & {
    agentRegistry?: Record<string, AgentContractLike>;
    taskRegistry?: Record<string, TaskContractLike>;
    handoffSchemas?: Record<string, z.ZodType>;
    retry?: {
        condition: string;
        fix_task: string;
        revalidate_task?: string;
    };
}): Promise<TaskRunResult>;

export { type AdapterSendOptions as A, type CacheConfig as C, InMemoryStore as I, type MemoryRef as M, type PromptBuilderOptions as P, type RetryDecision as R, type SdkAdapter as S, type TaskOutcome as T, type AgentExecutionRequest as a, type TaskContractLike as b, type AgentContractLike as c, type TaskContext as d, type TaskRunResult as e, type AgentProgressEvent as f, type CandidateAgent as g, type MemoryStore as h, type SplitPrompt as i, type TaskRunOptions as j, buildCandidateAgents as k, buildRetryFollowUp as l, buildSplitTaskPrompt as m, buildTaskPrompt as n, extractStructuredResult as o, runTask as p, zodSchemaToYamlExample as q, renderAgentSystemPrompt as r, zodSchemaToPromptDescription as z };
