"""Type stubs for the native Rust extension module."""

from typing import Any, Callable, Dict, List, Optional, Tuple

# ─── State ───────────────────────────────────────────────────────────────────

class SharedState:
    """Thread-safe shared state (default state type).

    A dict-like object backed by Arc<RwLock<PlainState>> in Rust.
    """

    def __init__(self, initial: Optional[Dict[str, Any]] = None) -> None: ...
    def get(self, key: str) -> Any: ...
    def set(self, key: str, value: Any) -> None: ...
    def contains_key(self, key: str) -> bool: ...
    def remove(self, key: str) -> Any: ...
    def keys(self) -> List[str]: ...
    def to_dict(self) -> Dict[str, Any]: ...
    def to_json(self) -> str: ...
    @staticmethod
    def from_dict(d: Dict[str, Any]) -> "SharedState": ...
    @staticmethod
    def from_json(json_str: str) -> "SharedState": ...
    def get_string(self, key: str) -> Optional[str]: ...
    def deep_clone(self) -> "SharedState": ...
    def __getitem__(self, key: str) -> Any: ...
    def __setitem__(self, key: str, value: Any) -> None: ...
    def __delitem__(self, key: str) -> None: ...
    def __contains__(self, key: str) -> bool: ...
    def __len__(self) -> int: ...
    def __repr__(self) -> str: ...
    def __str__(self) -> str: ...

class PlainState:
    """Owned state (not thread-safe, for direct manipulation)."""

    def __init__(self, initial: Optional[Dict[str, Any]] = None) -> None: ...
    def get(self, key: str) -> Any: ...
    def set(self, key: str, value: Any) -> None: ...
    def contains_key(self, key: str) -> bool: ...
    def remove(self, key: str) -> Any: ...
    def keys(self) -> List[str]: ...
    def to_dict(self) -> Dict[str, Any]: ...
    def to_json(self) -> str: ...
    @staticmethod
    def from_dict(d: Dict[str, Any]) -> "PlainState": ...
    @staticmethod
    def from_json(json_str: str) -> "PlainState": ...
    def get_string(self, key: str) -> Optional[str]: ...
    def get_int(self, key: str) -> Optional[int]: ...
    def get_float(self, key: str) -> Optional[float]: ...
    def get_bool(self, key: str) -> Optional[bool]: ...
    def __getitem__(self, key: str) -> Any: ...
    def __setitem__(self, key: str, value: Any) -> None: ...
    def __contains__(self, key: str) -> bool: ...
    def __len__(self) -> int: ...
    def __repr__(self) -> str: ...

# ─── Agent ───────────────────────────────────────────────────────────────────

class Agent:
    """The Agent - main interface to FlowgentraAI."""

    @staticmethod
    def from_config_path(config_path: str) -> "Agent": ...
    @staticmethod
    def from_config(config: "AgentConfig") -> "Agent": ...
    @property
    def state(self) -> SharedState: ...
    def set_state(self, key: str, value: Any) -> None: ...
    def run(self) -> SharedState: ...
    def run_with_thread(self, thread_id: str) -> SharedState: ...
    @property
    def config(self) -> "AgentConfig": ...
    @property
    def name(self) -> str: ...
    def __repr__(self) -> str: ...

# ─── Config ──────────────────────────────────────────────────────────────────

class AgentConfig:
    """Agent configuration loaded from YAML."""

    @staticmethod
    def from_file(path: str) -> "AgentConfig": ...
    @staticmethod
    def from_yaml(yaml_str: str) -> "AgentConfig": ...
    def validate(self) -> None: ...
    @property
    def name(self) -> str: ...
    @property
    def description(self) -> str: ...
    def to_json(self) -> str: ...
    def __repr__(self) -> str: ...

class StateField:
    """A field in the state schema."""

    def __init__(self, field_type: str, description: str) -> None: ...
    @property
    def field_type(self) -> str: ...
    @property
    def description(self) -> str: ...
    def __repr__(self) -> str: ...

# ─── Graph ───────────────────────────────────────────────────────────────────

END: str
"""The END sentinel constant ("__end__"). Use as edge target to terminate the graph."""

class StateGraphBuilder:
    """Build a state graph with Python callables as nodes.

    Example::

        from flowgentra_ai import StateGraphBuilder, SharedState, END

        def process(state):
            state["output"] = state["input"].upper()
            return state

        builder = StateGraphBuilder()
        builder.add_node("process", process)
        builder.set_entry_point("process")
        builder.add_edge("process", END)
        graph = builder.compile()

        result = graph.invoke(SharedState({"input": "hello"}))
        print(result.to_dict())  # {"input": "hello", "output": "HELLO"}
    """

    def __init__(self) -> None: ...
    def add_node(self, name: str, func: Callable[[SharedState], SharedState]) -> None: ...
    def add_edge(self, from_node: str, to_node: str) -> None: ...
    def add_conditional_edge(
        self, from_node: str, router: Callable[[SharedState], str]
    ) -> None: ...
    def set_entry_point(self, name: str) -> None: ...
    def set_max_steps(self, max_steps: int) -> None: ...
    def interrupt_before(self, name: str) -> None: ...
    def interrupt_after(self, name: str) -> None: ...
    def add_subgraph(self, name: str, subgraph: "StateGraph") -> None: ...
    def set_checkpointer(self, base_dir: str) -> None: ...
    def compile(self) -> "StateGraph": ...
    def __repr__(self) -> str: ...

class StateGraph:
    """A compiled, runnable state graph.

    Execute it with ``invoke()`` or ``invoke_with_thread()``.
    """

    def invoke(self, state: SharedState) -> SharedState: ...
    def invoke_with_thread(self, thread_id: str, state: SharedState) -> SharedState: ...
    def resume(self, thread_id: str) -> SharedState: ...
    def resume_with_state(self, thread_id: str, updates: SharedState) -> SharedState: ...
    def node_names(self) -> List[str]: ...
    def entry_point(self) -> str: ...
    def to_dot(self) -> str: ...
    def to_mermaid(self) -> str: ...
    def to_json(self) -> Any: ...
    def __repr__(self) -> str: ...

def graph_end() -> str:
    """Return the END constant string."""
    ...

# ─── LLM ─────────────────────────────────────────────────────────────────────

class LLMConfig:
    """LLM provider configuration."""

    def __init__(
        self,
        provider: str,
        model: str,
        api_key: str = "",
        temperature: Optional[float] = None,
        max_tokens: Optional[int] = None,
        top_p: Optional[float] = None,
    ) -> None: ...
    @property
    def provider(self) -> str: ...
    @property
    def model(self) -> str: ...
    @property
    def temperature(self) -> Optional[float]: ...
    @temperature.setter
    def temperature(self, val: Optional[float]) -> None: ...
    @property
    def max_tokens(self) -> Optional[int]: ...
    @max_tokens.setter
    def max_tokens(self, val: Optional[int]) -> None: ...
    @property
    def top_p(self) -> Optional[float]: ...
    @top_p.setter
    def top_p(self, val: Optional[float]) -> None: ...
    @property
    def api_key(self) -> str: ...
    def set_response_format(self, format: "ResponseFormat") -> None: ...
    def __repr__(self) -> str: ...

class ResponseFormat:
    """Response format for LLM output."""
    @staticmethod
    def text() -> "ResponseFormat": ...
    @staticmethod
    def json() -> "ResponseFormat": ...
    @staticmethod
    def json_schema(name: str, schema: Any) -> "ResponseFormat": ...
    def __repr__(self) -> str: ...
    def __str__(self) -> str: ...

class Message:
    """A message in a conversation."""

    def __init__(self, role: str, content: str, tool_call_id: Optional[str] = None) -> None: ...
    @staticmethod
    def system(content: str) -> "Message": ...
    @staticmethod
    def user(content: str) -> "Message": ...
    @staticmethod
    def assistant(content: str) -> "Message": ...
    @staticmethod
    def tool(content: str, tool_call_id: Optional[str] = None) -> "Message": ...
    @property
    def role(self) -> str: ...
    @property
    def content(self) -> str: ...
    @content.setter
    def content(self, val: str) -> None: ...
    @property
    def tool_call_id(self) -> Optional[str]: ...
    def has_tool_calls(self) -> bool: ...
    def is_system(self) -> bool: ...
    def is_user(self) -> bool: ...
    def is_assistant(self) -> bool: ...
    def is_tool(self) -> bool: ...
    def tool_calls(self) -> List["ToolCall"]: ...
    def __repr__(self) -> str: ...
    def __str__(self) -> str: ...

class ToolCall:
    """A tool call made by the LLM."""

    def __init__(self, id: str, name: str, arguments: Any) -> None: ...
    @property
    def id(self) -> str: ...
    @property
    def name(self) -> str: ...
    @property
    def arguments(self) -> Any: ...
    def __repr__(self) -> str: ...

class ToolDefinition:
    """A tool definition passed to the LLM."""

    def __init__(self, name: str, description: str, parameters: Any) -> None: ...
    @property
    def name(self) -> str: ...
    @property
    def description(self) -> str: ...
    @property
    def parameters(self) -> Any: ...
    def __repr__(self) -> str: ...

class TokenUsage:
    """Token usage statistics from an LLM response."""

    def __init__(self, prompt_tokens: int, completion_tokens: int) -> None: ...
    @property
    def prompt_tokens(self) -> int: ...
    @property
    def completion_tokens(self) -> int: ...
    @property
    def total_tokens(self) -> int: ...
    def estimated_cost(self, model: str) -> Optional[float]: ...
    def __repr__(self) -> str: ...

# ─── RAG ─────────────────────────────────────────────────────────────────────

class Document:
    """A document for RAG."""

    def __init__(
        self, id: str, content: str, metadata: Optional[Dict[str, Any]] = None
    ) -> None: ...
    @property
    def id(self) -> str: ...
    @property
    def content(self) -> str: ...
    @content.setter
    def content(self, val: str) -> None: ...
    @property
    def metadata(self) -> Dict[str, Any]: ...
    @property
    def embedding(self) -> Optional[List[float]]: ...
    def __repr__(self) -> str: ...

class SearchResult:
    """A search result from a vector store query."""

    @property
    def document(self) -> Document: ...
    @property
    def score(self) -> float: ...
    def __repr__(self) -> str: ...

class TextChunk:
    """A chunk of text from text splitting."""

    @property
    def text(self) -> str: ...
    @property
    def metadata(self) -> "ChunkMetadata": ...
    @property
    def start(self) -> int: ...
    @property
    def end(self) -> int: ...
    def __repr__(self) -> str: ...
    def __len__(self) -> int: ...

# ─── Memory ──────────────────────────────────────────────────────────────────

class Checkpoint:
    """A state checkpoint for persistence/resume."""

    @property
    def metadata(self) -> "CheckpointMetadata": ...
    @property
    def state(self) -> Any: ...
    def __repr__(self) -> str: ...

class CheckpointMetadata:
    """Metadata for a checkpoint."""

    @property
    def thread_id(self) -> str: ...
    @property
    def node_name(self) -> str: ...
    @property
    def step(self) -> int: ...
    @property
    def timestamp(self) -> str: ...
    def __repr__(self) -> str: ...

# ─── Evaluation ──────────────────────────────────────────────────────────────

class EvaluationResult:
    """Result of an auto-evaluation node."""

    def __init__(self, score: float, passed: bool, feedback: str) -> None: ...
    @property
    def score(self) -> float: ...
    @property
    def passed(self) -> bool: ...
    @property
    def feedback(self) -> str: ...
    def __repr__(self) -> str: ...

# ─── Tools ───────────────────────────────────────────────────────────────────

class ToolCallRequest:
    """A request to call a tool."""

    def __init__(self, name: str, arguments: Any) -> None: ...
    @property
    def name(self) -> str: ...
    @property
    def arguments(self) -> Any: ...
    def __repr__(self) -> str: ...

class ToolCallResult:
    """Result from a tool call."""

    def __init__(self, tool_call_id: str, content: str, success: bool) -> None: ...
    @property
    def tool_call_id(self) -> str: ...
    @property
    def content(self) -> str: ...
    @property
    def success(self) -> bool: ...
    def __repr__(self) -> str: ...

# ─── LLM Client ─────────────────────────────────────────────────────────────

class LLMClient:
    """LLM client for making API calls to language models."""

    @staticmethod
    def from_config(config: LLMConfig) -> "LLMClient": ...
    def chat(self, messages: List[Message]) -> Message: ...
    def chat_with_usage(self, messages: List[Message]) -> tuple: ...
    def chat_with_tools(
        self, messages: List[Message], tools: List[ToolDefinition]
    ) -> Message: ...
    def cached(self, max_entries: int = 100) -> "LLMClient":
        """Wrap with a response cache."""
        ...
    def with_fallback(self, fallback: "LLMClient") -> "LLMClient":
        """Create a fallback client."""
        ...
    def with_retry(self, max_retries: int = 3) -> "LLMClient":
        """Wrap with automatic retry and backoff."""
        ...
    def __repr__(self) -> str: ...

# ─── Prebuilt Agents ────────────────────────────────────────────────────────

class AgentType:
    """Agent type: zero_shot_react, few_shot_react, or conversational."""

    @staticmethod
    def zero_shot_react() -> "AgentType": ...
    @staticmethod
    def few_shot_react() -> "AgentType": ...
    @staticmethod
    def conversational() -> "AgentType": ...
    def __repr__(self) -> str: ...
    def __str__(self) -> str: ...

class ToolSpec:
    """Tool specification for prebuilt agents."""

    def __init__(self, name: str, description: str) -> None: ...
    def add_parameter(self, name: str, param_type: str) -> None: ...
    def set_required(self, param: str) -> None: ...
    @property
    def name(self) -> str: ...
    @property
    def description(self) -> str: ...
    def __repr__(self) -> str: ...

class AgentBuilder:
    """Builder for creating prebuilt agents."""

    def __init__(self, agent_type: AgentType) -> None: ...
    def with_name(self, name: str) -> None: ...
    def with_llm_config(self, model: str) -> None: ...
    def with_temperature(self, temperature: float) -> None: ...
    def with_max_tokens(self, tokens: int) -> None: ...
    def with_tool(self, tool: ToolSpec) -> None: ...
    def with_system_prompt(self, prompt: str) -> None: ...
    def with_memory_steps(self, steps: int) -> None: ...
    def with_evaluation(self) -> None: ...
    def with_retries(self, max_retries: int) -> None: ...
    def with_param(self, key: str, value: str) -> None: ...
    def build_graph(self) -> "GraphBasedAgent": ...
    def __repr__(self) -> str: ...

class GraphBasedAgent:
    """A graph-based prebuilt agent (ReAct, Conversational, etc.)."""

    def execute_input(self, input: str) -> str: ...
    @property
    def name(self) -> str: ...
    def node_names(self) -> List[str]: ...
    def __repr__(self) -> str: ...

# ─── Tool Registry ──────────────────────────────────────────────────────────

class JsonSchema:
    """JSON Schema for tool input/output validation."""

    @staticmethod
    def object() -> "JsonSchema": ...
    @staticmethod
    def string() -> "JsonSchema": ...
    @staticmethod
    def number() -> "JsonSchema": ...
    @staticmethod
    def integer() -> "JsonSchema": ...
    @staticmethod
    def boolean() -> "JsonSchema": ...
    @staticmethod
    def array() -> "JsonSchema": ...
    def with_description(self, desc: str) -> None: ...
    def with_required(self, fields: List[str]) -> None: ...
    def validate(self, value: Any) -> None: ...
    @property
    def schema_type(self) -> str: ...
    @property
    def description(self) -> Optional[str]: ...
    def __repr__(self) -> str: ...

class ToolRegistry:
    """Central registry for managing tools."""

    def __init__(self) -> None: ...
    @staticmethod
    def with_builtins() -> "ToolRegistry": ...
    def call_tool(self, name: str, input: Any) -> Any: ...
    def validate_input(self, name: str, input: Any) -> None: ...
    def list_names(self) -> List[str]: ...
    def __len__(self) -> int: ...
    def __repr__(self) -> str: ...

# ─── Text Splitters ─────────────────────────────────────────────────────────

class RecursiveCharacterTextSplitter:
    """Split text by recursively trying different separators."""

    def __init__(self, chunk_size: int = 1000, chunk_overlap: int = 200) -> None: ...
    def split_text(self, text: str) -> List[TextChunk]: ...
    def split_with_source(self, text: str, source: str) -> List[TextChunk]: ...
    def __repr__(self) -> str: ...

class MarkdownTextSplitter:
    """Split markdown text by headers and code blocks."""

    def __init__(self, chunk_size: int = 1000, chunk_overlap: int = 200) -> None: ...
    def split_text(self, text: str) -> List[TextChunk]: ...
    def __repr__(self) -> str: ...

class HTMLTextSplitter:
    """Split HTML text by tags."""

    def __init__(self, chunk_size: int = 1000, chunk_overlap: int = 200) -> None: ...
    def split_text(self, text: str) -> List[TextChunk]: ...
    def __repr__(self) -> str: ...

class TokenTextSplitter:
    """Split text by estimated token count."""

    def __init__(self, max_tokens: int = 500, overlap_tokens: int = 50) -> None: ...
    def split_text(self, text: str) -> List[TextChunk]: ...
    def __repr__(self) -> str: ...

class CodeTextSplitter:
    """Split source code by language-specific syntax."""

    def __init__(
        self, language: str, chunk_size: int = 1000, chunk_overlap: int = 200
    ) -> None: ...
    def split_text(self, text: str) -> List[TextChunk]: ...
    def __repr__(self) -> str: ...

# ─── Conversation Memory ────────────────────────────────────────────────────

class ConversationMemory:
    """In-memory conversation memory with optional sliding window."""

    def __init__(self, max_messages: Optional[int] = None) -> None: ...
    def add_message(self, thread_id: str, message: Message) -> None: ...
    def messages(
        self, thread_id: str, limit: Optional[int] = None
    ) -> List[Message]: ...
    def clear(self, thread_id: str) -> None: ...
    def __repr__(self) -> str: ...

class TokenBufferMemory:
    """Token-aware conversation memory that trims to a token budget."""

    def __init__(self, max_tokens: int = 4000) -> None: ...
    def add_message(self, thread_id: str, message: Message) -> None: ...
    def messages(
        self, thread_id: str, limit: Optional[int] = None
    ) -> List[Message]: ...
    def clear(self, thread_id: str) -> None: ...
    def __repr__(self) -> str: ...

class SummaryConfig:
    """Configuration for SummaryMemory."""

    def __init__(
        self, buffer_size: int = 10, max_summary_tokens: int = 200
    ) -> None: ...
    @property
    def buffer_size(self) -> int: ...
    @property
    def max_summary_tokens(self) -> int: ...
    def __repr__(self) -> str: ...

class SummaryMemory:
    """Conversation memory with automatic summarization."""

    def __init__(self, config: SummaryConfig, summarize_fn: Callable[[str], str]) -> None: ...
    def add_message(self, thread_id: str, message: Message) -> None: ...
    def messages(
        self, thread_id: str, limit: Optional[int] = None
    ) -> List[Message]: ...
    def clear(self, thread_id: str) -> None: ...
    def get_summary(self, thread_id: str) -> Optional[str]: ...
    def summarize_if_needed(self, thread_id: str) -> None: ...
    def __repr__(self) -> str: ...

class FileCheckpointer:
    """File-based checkpointer for persisting graph state to disk."""

    def __init__(self, base_dir: str) -> None: ...
    def save(
        self,
        thread_id: str,
        step: int,
        node_name: str,
        state: "SharedState",
    ) -> None: ...
    def load(self, thread_id: str, step: int) -> Optional[Dict[str, Any]]: ...
    def load_latest(self, thread_id: str) -> Optional[Dict[str, Any]]: ...
    def list_checkpoints(self, thread_id: str) -> List[Tuple[int, int]]: ...
    def delete(self, thread_id: str, step: int) -> None: ...
    def delete_thread(self, thread_id: str) -> None: ...
    def __repr__(self) -> str: ...

# ─── Prompt & Parsers ───────────────────────────────────────────────────────

class PromptTemplate:
    """A prompt template with variable substitution using {variable_name}."""

    def __init__(self, template: str) -> None: ...
    def input_variables(self) -> List[str]: ...
    def format(self, variables: Dict[str, str]) -> str: ...
    def __repr__(self) -> str: ...

class JsonOutputParser:
    """Parse JSON output from LLM responses."""

    def __init__(self, schema_hint: Optional[str] = None) -> None: ...
    def parse(self, text: str) -> Any: ...
    def format_instructions(self) -> str: ...
    def __repr__(self) -> str: ...

class ListOutputParser:
    """Parse a list from LLM output."""

    def __init__(self, separator: str = "comma") -> None: ...
    def parse(self, text: str) -> List[str]: ...
    def format_instructions(self) -> str: ...
    def __repr__(self) -> str: ...

# ─── Free functions ──────────────────────────────────────────────────────────

def py_from_config_path(config_path: str) -> Agent:
    """Create an agent from a YAML config file."""
    ...

# ─── Vector Store & Embeddings ───────────────────────────────────────────────

class Embeddings:
    """Embeddings manager for generating vector embeddings from text."""

    @staticmethod
    def mock(dimension: int) -> "Embeddings": ...
    @staticmethod
    def openai(api_key: str, model: str = "text-embedding-3-small") -> "Embeddings": ...
    @staticmethod
    def openai_with_dimension(api_key: str, model: str, dimension: int) -> "Embeddings": ...
    @staticmethod
    def openai_cached(api_key: str, model: str = "text-embedding-3-small") -> "Embeddings": ...
    @staticmethod
    def huggingface(
        model: str,
        api_key: str,
        endpoint: Optional[str] = None,
        dimension: Optional[int] = None,
    ) -> "Embeddings": ...
    @staticmethod
    def ollama(
        model: str,
        base_url: Optional[str] = None,
        dimension: Optional[int] = None,
    ) -> "Embeddings": ...
    @staticmethod
    def mistral(api_key: str, model: Optional[str] = None) -> "Embeddings": ...
    def embed(self, text: str) -> List[float]: ...
    def embed_batch(self, texts: List[str]) -> List[List[float]]: ...
    def get_dimension(self) -> int: ...
    def __repr__(self) -> str: ...

class InMemoryVectorStore:
    """In-memory vector store with cosine similarity search."""

    def __init__(self) -> None: ...
    def index(self, doc: Document, embedding: List[float]) -> None: ...
    def search(
        self,
        query_embedding: List[float],
        top_k: int = 5,
        filter: Optional[Dict[str, Any]] = None,
    ) -> List[SearchResult]: ...
    def delete(self, doc_id: str) -> None: ...
    def get(self, doc_id: str) -> Document: ...
    def list(self) -> List[Document]: ...
    def clear(self) -> None: ...
    def __repr__(self) -> str: ...

class RetrievalConfig:
    """Configuration for retrieval strategies."""

    @staticmethod
    def semantic(top_k: int = 5, threshold: float = 0.7) -> "RetrievalConfig": ...
    @staticmethod
    def hybrid(
        keyword_weight: float = 0.3, top_k: int = 5, threshold: float = 0.7
    ) -> "RetrievalConfig": ...
    @property
    def top_k(self) -> int: ...
    @property
    def similarity_threshold(self) -> float: ...
    def __repr__(self) -> str: ...

class Retriever:
    """Full retrieval pipeline: embed -> search -> hybrid -> rerank -> dedup."""

    def __init__(
        self,
        store: InMemoryVectorStore,
        embeddings: Embeddings,
        config: RetrievalConfig,
    ) -> None: ...
    def with_dedup(self, threshold: float) -> None: ...
    def retrieve(self, query: str) -> List[SearchResult]: ...
    def __repr__(self) -> str: ...

# ─── Message Graph ───────────────────────────────────────────────────────────

class MessageGraph:
    """A compiled message-centric graph."""

    def invoke(self, messages: List[Message]) -> List[Message]: ...
    def __repr__(self) -> str: ...

class MessageGraphBuilder:
    """Convenience builder for chat-focused workflows."""

    def __init__(self) -> None: ...
    def add_node(
        self, name: str, func: Callable[[List[Message]], List[Message]]
    ) -> None: ...
    def add_edge(self, from_node: str, to_node: str) -> None: ...
    def set_entry_point(self, name: str) -> None: ...
    def compile(self) -> MessageGraph: ...
    def __repr__(self) -> str: ...

# ─── Supervisor ──────────────────────────────────────────────────────────────

class Supervisor:
    """Multi-agent supervisor that orchestrates named agent graphs."""

    def __init__(self, router: Callable[[SharedState], str]) -> None: ...
    def add_agent(self, name: str, graph: StateGraph) -> None: ...
    def max_rounds(self, rounds: int) -> None: ...
    def finish_marker(self, marker: str) -> None: ...
    def run(self, state: SharedState) -> SharedState: ...
    def agent_names(self) -> List[str]: ...
    def __repr__(self) -> str: ...

# ─── Routing Conditions ─────────────────────────────────────────────────────

class ComparisonOp:
    """Comparison operator for field comparisons."""

    @staticmethod
    def equal() -> "ComparisonOp": ...
    @staticmethod
    def not_equal() -> "ComparisonOp": ...
    @staticmethod
    def less_than() -> "ComparisonOp": ...
    @staticmethod
    def less_or_equal() -> "ComparisonOp": ...
    @staticmethod
    def greater_than() -> "ComparisonOp": ...
    @staticmethod
    def greater_or_equal() -> "ComparisonOp": ...
    def __repr__(self) -> str: ...
    def __str__(self) -> str: ...

class Condition:
    """Type-safe routing condition for graph edges."""

    @staticmethod
    def compare(field: str, op: ComparisonOp, value: Any) -> "Condition": ...
    @staticmethod
    def field_exists(field: str) -> "Condition": ...
    @staticmethod
    def field_type(field: str, expected_type: str) -> "Condition": ...
    @staticmethod
    def and_conditions(conditions: List["Condition"]) -> "Condition": ...
    @staticmethod
    def or_conditions(conditions: List["Condition"]) -> "Condition": ...
    @staticmethod
    def not_condition(condition: "Condition") -> "Condition": ...
    def evaluate(self, state: SharedState) -> bool: ...
    def simplify(self) -> "Condition": ...
    def __repr__(self) -> str: ...
    def __str__(self) -> str: ...

class ConditionBuilder:
    """Builder for constructing complex conditions."""

    @staticmethod
    def and_builder() -> "ConditionBuilder": ...
    @staticmethod
    def or_builder() -> "ConditionBuilder": ...
    def compare(self, field: str, op: ComparisonOp, value: Any) -> None: ...
    def field_exists(self, field: str) -> None: ...
    def add_condition(self, condition: Condition) -> None: ...
    def build(self) -> Condition: ...
    def __repr__(self) -> str: ...

# ─── Observability ───────────────────────────────────────────────────────────

class ExecutionTrace:
    """A recorded execution trace of graph execution."""

    def __init__(self, agent_name: Optional[str] = None) -> None: ...
    def execution_path(self) -> List[str]: ...
    def total_duration_ms(self) -> Optional[int]: ...
    def to_json(self) -> str: ...
    @staticmethod
    def from_json(json_str: str) -> "ExecutionTrace": ...
    def __repr__(self) -> str: ...

class ExecutionTracer:
    """Records execution events for graph visualization and debugging."""

    def __init__(self) -> None: ...
    def trace_node_start(self, node_id: str) -> None: ...
    def trace_node_end(self, node_id: str, duration_ms: int, success: bool) -> None: ...
    def trace_edge_traversal(self, from_: str, to: str, condition_met: bool) -> None: ...
    def trace_state_update(self, key: str, value: str) -> None: ...
    def trace_custom(self, event_name: str, details: Optional[str] = None) -> None: ...
    def get_events_json(self) -> str: ...
    def clear(self) -> None: ...
    def __repr__(self) -> str: ...

def py_init_tracing(log_level: str = "info") -> None:
    """Initialize tracing subscriber with structured logging."""
    ...

# ─── MCP ─────────────────────────────────────────────────────────────────────

class MCPConfig:
    """MCP (Model Context Protocol) configuration."""

    @staticmethod
    def sse(url: str, name: Optional[str] = None) -> "MCPConfig": ...
    @staticmethod
    def stdio(
        command: str,
        args: Optional[List[str]] = None,
        name: Optional[str] = None,
    ) -> "MCPConfig": ...
    @staticmethod
    def docker(image: str, name: Optional[str] = None) -> "MCPConfig": ...
    def is_remote(self) -> bool: ...
    def is_local(self) -> bool: ...
    @property
    def name(self) -> str: ...
    def __repr__(self) -> str: ...

# ─── Free functions ──────────────────────────────────────────────────────────

def py_chunk_text(text: str, chunk_size: int, overlap: int = 0) -> List[str]:
    """Split text into chunks."""
    ...

def py_extract_text(path: str) -> str:
    """Extract text from a PDF file."""
    ...

def py_estimate_tokens(text: str) -> int:
    """Estimate token count for text."""
    ...

def py_model_pricing(model: str) -> Optional[Tuple[float, float]]:
    """Get model pricing (input_per_million, output_per_million) in USD."""
    ...

def py_from_config_path(path: str) -> Any:
    """Create agent from config file path."""
    ...

def py_init_tracing(log_level: str = "info") -> None:
    """Initialize tracing subscriber."""
    ...

# ─── Document Loaders ───────────────────────────────────────────────────────

class FileType:
    """File type detected from extension."""
    @staticmethod
    def from_path(path: str) -> "FileType": ...
    @staticmethod
    def plain_text() -> "FileType": ...
    @staticmethod
    def markdown() -> "FileType": ...
    @staticmethod
    def html() -> "FileType": ...
    @staticmethod
    def pdf() -> "FileType": ...
    @staticmethod
    def unknown() -> "FileType": ...
    def __repr__(self) -> str: ...
    def __str__(self) -> str: ...

class LoadedDocument:
    """A document loaded from a file."""
    @property
    def id(self) -> str: ...
    @property
    def text(self) -> str: ...
    @property
    def source(self) -> str: ...
    @property
    def file_type(self) -> FileType: ...
    def __repr__(self) -> str: ...

def py_load_document(path: str) -> LoadedDocument:
    """Load a single document from a file path."""
    ...

def py_load_directory(dir: str) -> List[LoadedDocument]:
    """Load all documents from a directory."""
    ...

# ─── Ingestion Pipeline ─────────────────────────────────────────────────────

class IngestionStats:
    """Statistics from an ingestion run."""
    @property
    def documents_processed(self) -> int: ...
    @property
    def chunks_indexed(self) -> int: ...
    @property
    def errors(self) -> List[str]: ...
    def __repr__(self) -> str: ...

class IngestionPipeline:
    """Pipeline for ingesting documents into a vector store."""
    def __init__(
        self,
        store: "InMemoryVectorStore",
        embeddings: "Embeddings",
        batch_size: int = 10,
    ) -> None: ...
    def ingest(self, documents: List[Tuple[str, str]]) -> IngestionStats: ...
    def ingest_with_metadata(
        self, documents: List[Tuple[str, str, Dict[str, Any]]]
    ) -> IngestionStats: ...
    def __repr__(self) -> str: ...

# ─── RAG Evaluation ─────────────────────────────────────────────────────────

class EvalQuery:
    """A query with known relevant document IDs for evaluation."""
    def __init__(self, query: str, relevant_doc_ids: List[str]) -> None: ...
    @property
    def query(self) -> str: ...
    @property
    def relevant_doc_ids(self) -> List[str]: ...
    def __repr__(self) -> str: ...

class QueryResult:
    """Per-query evaluation result."""
    @property
    def query(self) -> str: ...
    @property
    def hit(self) -> bool: ...
    @property
    def reciprocal_rank(self) -> float: ...
    @property
    def ndcg(self) -> float: ...
    @property
    def retrieved_ids(self) -> List[str]: ...
    def __repr__(self) -> str: ...

class EvalResults:
    """Aggregate evaluation results across all queries."""
    @property
    def hit_rate(self) -> float: ...
    @property
    def mrr(self) -> float: ...
    @property
    def ndcg(self) -> float: ...
    @property
    def num_queries(self) -> int: ...
    @property
    def per_query(self) -> List[QueryResult]: ...
    def __repr__(self) -> str: ...

def py_hit_rate(queries: List[EvalQuery], retrieved: List[List[str]]) -> float:
    """Compute hit rate metric."""
    ...

def py_mrr(queries: List[EvalQuery], retrieved: List[List[str]]) -> float:
    """Compute mean reciprocal rank."""
    ...

def py_mean_ndcg(queries: List[EvalQuery], retrieved: List[List[str]]) -> float:
    """Compute mean NDCG."""
    ...

def py_rag_evaluate(queries: List[EvalQuery], retrieved: List[List[str]]) -> EvalResults:
    """Run full RAG evaluation."""
    ...

# ─── PDF Utilities ───────────────────────────────────────────────────────────

class PdfDocument:
    """Represents an extracted PDF document."""
    @property
    def source(self) -> str: ...
    @property
    def page_count(self) -> int: ...
    @property
    def text(self) -> str: ...
    def __repr__(self) -> str: ...

def py_extract_pdf(path: str) -> PdfDocument:
    """Extract a PDF into a PdfDocument object."""
    ...

def py_chunk_text_by_tokens(text: str, max_tokens: int, overlap_tokens: int = 0) -> List[str]:
    """Split text into chunks by token count."""
    ...

def py_extract_and_chunk(
    path: str, chunk_size: int = 1000, overlap: int = 200
) -> List[Tuple[str, str]]:
    """Extract text from a PDF and split into (id, text) chunks."""
    ...

# ─── Rerankers ───────────────────────────────────────────────────────────────

class NoopReranker:
    """A no-op reranker that passes results through unchanged."""
    def __init__(self) -> None: ...
    def rerank(self, query: str, results: List["SearchResult"]) -> List["SearchResult"]: ...
    def __repr__(self) -> str: ...

class RRFReranker:
    """Reciprocal Rank Fusion reranker for merging multiple result lists."""
    def __init__(self, k: int = 60) -> None: ...
    def fuse(self, result_lists: List[List["SearchResult"]]) -> List["SearchResult"]: ...
    def __repr__(self) -> str: ...

class CrossEncoderReranker:
    """Cross-encoder reranker using an external API endpoint."""
    def __init__(
        self,
        endpoint: str,
        api_key: Optional[str] = None,
        top_k: Optional[int] = None,
    ) -> None: ...
    def rerank(self, query: str, results: List["SearchResult"]) -> List["SearchResult"]: ...
    def __repr__(self) -> str: ...

# ─── Hybrid Search & Dedup ───────────────────────────────────────────────────

def py_bm25_score(query: str, documents: List[str]) -> List[float]:
    """Compute BM25 scores for a query against documents."""
    ...

def py_hybrid_merge(
    results: List["SearchResult"], query: str, keyword_weight: float = 0.3
) -> List["SearchResult"]:
    """Merge semantic results with keyword scores."""
    ...

def py_dedup_by_id(results: List["SearchResult"]) -> List["SearchResult"]:
    """Deduplicate search results by document ID."""
    ...

def py_dedup_by_similarity(
    results: List["SearchResult"], threshold: float = 0.85
) -> List["SearchResult"]:
    """Deduplicate search results by text similarity threshold."""
    ...

def py_decompose_query(query: str, max_depth: int = 2) -> List[str]:
    """Decompose a compound query into sub-queries."""
    ...

# ─── ChromaDB ───────────────────────────────────────────────────────────────

class ChromaStore:
    """ChromaDB vector store backend."""
    def __init__(
        self,
        collection_name: str,
        endpoint: str = "http://localhost:8000",
        embedding_dim: int = 1536,
    ) -> None: ...
    def index(self, doc: "Document", embedding: List[float]) -> None: ...
    def search(
        self,
        query_embedding: List[float],
        top_k: int = 5,
        filter: Optional[Dict[str, Any]] = None,
    ) -> List["SearchResult"]: ...
    def delete(self, doc_id: str) -> None: ...
    def update(self, doc: "Document", embedding: Optional[List[float]] = None) -> None: ...
    def get(self, doc_id: str) -> "Document": ...
    def list(self) -> List["Document"]: ...
    def clear(self) -> None: ...
    def __repr__(self) -> str: ...

# ─── Built-in Tools ─────────────────────────────────────────────────────────

class CalculatorTool:
    """Built-in calculator tool for mathematical expressions."""
    def __init__(self) -> None: ...
    def call(self, input: Dict[str, Any]) -> Dict[str, Any]: ...
    def definition(self) -> Dict[str, Any]: ...
    def __repr__(self) -> str: ...

class SearchTool:
    """Built-in search tool."""
    def __init__(self) -> None: ...
    def call(self, input: Dict[str, Any]) -> Dict[str, Any]: ...
    def definition(self) -> Dict[str, Any]: ...
    def __repr__(self) -> str: ...

class WebRequestTool:
    """Built-in web request tool."""
    def __init__(self) -> None: ...
    def call(self, input: Dict[str, Any]) -> Dict[str, Any]: ...
    def definition(self) -> Dict[str, Any]: ...
    def __repr__(self) -> str: ...

class FilesTool:
    """Built-in file system tool."""
    def __init__(self) -> None: ...
    def call(self, input: Dict[str, Any]) -> Dict[str, Any]: ...
    def definition(self) -> Dict[str, Any]: ...
    def __repr__(self) -> str: ...

# ─── Tool Node ──────────────────────────────────────────────────────────────

class ToolNode:
    """A node that executes tool calls from state."""
    def __repr__(self) -> str: ...

def py_create_tool_node(executor: Callable[[str, Dict[str, Any]], str]) -> ToolNode:
    """Create a tool node from a Python executor function."""
    ...

def py_store_tool_calls(state: PlainState, message: "Message") -> PlainState:
    """Extract tool calls from an LLM Message into state."""
    ...

def py_check_tools_condition(state: PlainState, tool_node_name: str) -> str:
    """Return tool_node_name if state has tool_calls, else '__end__'."""
    ...

# ─── Visualization ──────────────────────────────────────────────────────────

class VisualizationConfig:
    """Configuration for graph visualization."""
    def __init__(self, output_path: str = "agent_graph.svg") -> None: ...
    @property
    def output_path(self) -> str: ...
    def __repr__(self) -> str: ...

def py_visualize_graph(graph: StateGraph, config: VisualizationConfig) -> None:
    """Visualize a state graph, writing output to a file."""
    ...

def py_graph_to_dot(graph: StateGraph) -> str:
    """Export graph as a DOT string (Graphviz format)."""
    ...

def py_graph_to_mermaid(graph: StateGraph) -> str:
    """Export graph as a Mermaid diagram string."""
    ...

# ─── Advanced Nodes ─────────────────────────────────────────────────────────

class JoinType:
    """How to join parallel branches."""
    @staticmethod
    def wait_all() -> "JoinType": ...
    @staticmethod
    def wait_any() -> "JoinType": ...
    @staticmethod
    def wait_count(n: int) -> "JoinType": ...
    @staticmethod
    def wait_timeout() -> "JoinType": ...
    def __repr__(self) -> str: ...

class MergeStrategy:
    """Strategy for merging parallel branch results."""
    @staticmethod
    def combine() -> "MergeStrategy": ...
    @staticmethod
    def first() -> "MergeStrategy": ...
    @staticmethod
    def last() -> "MergeStrategy": ...
    @staticmethod
    def by_branch() -> "MergeStrategy": ...
    @staticmethod
    def custom() -> "MergeStrategy": ...
    def __repr__(self) -> str: ...

class BranchConfig:
    """Configuration for a single branch in parallel execution."""
    def __init__(self, name: str, handler: str) -> None: ...
    @property
    def name(self) -> str: ...
    @property
    def handler(self) -> str: ...
    def __repr__(self) -> str: ...

class LoopNodeConfig:
    """Configuration for a loop node."""
    def __init__(
        self,
        handler: str,
        max_iterations: int = 1,
        break_condition: Optional[str] = None,
        accumulate: bool = False,
    ) -> None: ...
    @property
    def handler(self) -> str: ...
    @property
    def max_iterations(self) -> int: ...
    @property
    def break_condition(self) -> Optional[str]: ...
    @property
    def accumulate_results(self) -> bool: ...
    def __repr__(self) -> str: ...

class ParallelNodeConfig:
    """Configuration for parallel branch execution."""
    def __init__(self, name: str) -> None: ...
    def add_branch(self, handler: str) -> None: ...
    def add_named_branch(self, name: str, handler: str) -> None: ...
    def set_join_type(self, join_type: JoinType) -> None: ...
    def set_timeout(self, timeout_ms: int) -> None: ...
    def set_continue_on_error(self, value: bool) -> None: ...
    @property
    def name(self) -> str: ...
    @property
    def branches(self) -> List[BranchConfig]: ...
    def __repr__(self) -> str: ...

class SubgraphNodeConfig:
    """Configuration for subgraph nodes."""
    def __init__(self, name: str, subgraph_path: str) -> None: ...
    def set_parameter(self, key: str, value: Any) -> None: ...
    def set_inherit_state(self, inherit: bool) -> None: ...
    def add_input_mapping(self, key: str) -> None: ...
    def add_output_mapping(self, key: str) -> None: ...
    def set_timeout(self, timeout_ms: int) -> None: ...
    @property
    def name(self) -> str: ...
    @property
    def subgraph_path(self) -> str: ...
    def __repr__(self) -> str: ...

class JoinNodeConfig:
    """Configuration for join points in parallel execution."""
    def __init__(self, name: str) -> None: ...
    def set_strategy(self, strategy: MergeStrategy) -> None: ...
    def add_merge_key(self, key: str) -> None: ...
    def set_fail_on_error(self, fail: bool) -> None: ...
    def set_merge_function(self, function: str) -> None: ...
    @property
    def name(self) -> str: ...
    def __repr__(self) -> str: ...

# ─── LLM Reranker ───────────────────────────────────────────────────────────

class LLMReranker:
    """LLM-based reranker that scores query-document pairs."""
    def __init__(self, score_fn: Callable[[str, str], float]) -> None: ...
    def rerank(self, query: str, results: List["SearchResult"]) -> List["SearchResult"]: ...
    def __repr__(self) -> str: ...

# ─── Memory-Aware Agent ─────────────────────────────────────────────────────

class MemoryStats:
    """Statistics about memory usage."""
    @property
    def message_count(self) -> int: ...
    @property
    def user_messages(self) -> int: ...
    @property
    def assistant_messages(self) -> int: ...
    @property
    def approximate_tokens(self) -> int: ...
    def __repr__(self) -> str: ...

class MemoryAwareAgent:
    """Agent with automatic conversation memory management."""
    @staticmethod
    def from_config(config_path: str) -> "MemoryAwareAgent": ...
    def set_thread_id(self, thread_id: str) -> None: ...
    def thread_id(self) -> str: ...
    def run_turn(self, input: str) -> str: ...
    def clear_memory(self) -> None: ...
    def memory_stats(self) -> MemoryStats: ...
    def __repr__(self) -> str: ...

# ─── RAG Config Types ───────────────────────────────────────────────────────

class VectorStoreType:
    """Vector store backend type."""
    @staticmethod
    def pinecone() -> "VectorStoreType": ...
    @staticmethod
    def weaviate() -> "VectorStoreType": ...
    @staticmethod
    def chroma() -> "VectorStoreType": ...
    @staticmethod
    def milvus() -> "VectorStoreType": ...
    @staticmethod
    def qdrant() -> "VectorStoreType": ...
    @staticmethod
    def memory() -> "VectorStoreType": ...
    def __repr__(self) -> str: ...

class RAGConfig:
    """Low-level RAG configuration for vector store connections."""
    @staticmethod
    def memory(embedding_dim: int = 1536) -> "RAGConfig": ...
    @staticmethod
    def chroma(endpoint: str = "http://localhost:8000") -> "RAGConfig": ...
    @staticmethod
    def pinecone(index: str, api_key: str) -> "RAGConfig": ...
    @staticmethod
    def qdrant(endpoint: str, collection: str, embedding_dim: int = 1536) -> "RAGConfig": ...
    @staticmethod
    def weaviate(endpoint: str) -> "RAGConfig": ...
    @property
    def store_type(self) -> VectorStoreType: ...
    @property
    def index_name(self) -> str: ...
    @property
    def embedding_dim(self) -> int: ...
    @property
    def endpoint(self) -> Optional[str]: ...
    def __repr__(self) -> str: ...

class VectorStoreConfig:
    """Vector store configuration for agent YAML config."""
    def __init__(
        self,
        store_type: VectorStoreType,
        collection: str = "documents",
        endpoint: Optional[str] = None,
        api_key: Optional[str] = None,
        embedding_dim: Optional[int] = None,
    ) -> None: ...
    @property
    def store_type(self) -> VectorStoreType: ...
    @property
    def collection(self) -> str: ...
    @property
    def endpoint(self) -> Optional[str]: ...
    @property
    def embedding_dim(self) -> Optional[int]: ...
    def __repr__(self) -> str: ...

class EmbeddingsConfig:
    """Embeddings provider configuration."""
    def __init__(
        self,
        provider: str,
        model: Optional[str] = None,
        api_key: Optional[str] = None,
        dimension: Optional[int] = None,
    ) -> None: ...
    @property
    def provider(self) -> str: ...
    @property
    def model(self) -> Optional[str]: ...
    @property
    def dimension(self) -> Optional[int]: ...
    def __repr__(self) -> str: ...

class RetrievalSettings:
    """Retrieval settings for RAG."""
    def __init__(self, top_k: int = 5, similarity_threshold: float = 0.7) -> None: ...
    @property
    def top_k(self) -> int: ...
    @property
    def similarity_threshold(self) -> float: ...
    def __repr__(self) -> str: ...

class PdfSettings:
    """PDF processing settings."""
    def __init__(self, chunk_size: int = 1000, chunk_overlap: int = 200) -> None: ...
    @property
    def chunk_size(self) -> int: ...
    @property
    def chunk_overlap(self) -> int: ...
    def __repr__(self) -> str: ...

class RAGGraphConfig:
    """Complete RAG configuration for agent graph config."""
    def __init__(
        self,
        vector_store: VectorStoreConfig,
        embeddings: EmbeddingsConfig,
        retrieval: Optional[RetrievalSettings] = None,
        pdf: Optional[PdfSettings] = None,
    ) -> None: ...
    @property
    def vector_store(self) -> VectorStoreConfig: ...
    @property
    def embeddings(self) -> EmbeddingsConfig: ...
    @property
    def retrieval(self) -> RetrievalSettings: ...
    @property
    def pdf(self) -> PdfSettings: ...
    def embedding_dimension(self) -> int: ...
    def __repr__(self) -> str: ...

# ─── Evaluation Config & Reporting ──────────────────────────────────────────

class ScoringConfig:
    """Scoring sub-configuration for evaluation."""
    def __init__(self, metrics: List[str] = ..., weights: List[float] = ...) -> None: ...
    @property
    def metrics(self) -> List[str]: ...
    @property
    def weights(self) -> List[float]: ...
    def __repr__(self) -> str: ...

class GradingConfig:
    """Grading sub-configuration for evaluation."""
    def __init__(self, enabled: bool = False, rubric: Optional[str] = None) -> None: ...
    @property
    def enabled(self) -> bool: ...
    @property
    def rubric(self) -> Optional[str]: ...
    def __repr__(self) -> str: ...

class EvaluationConfig:
    """Evaluation configuration for automatic agent evaluation."""
    def __init__(
        self,
        enabled: bool = True,
        min_confidence: float = 0.8,
        max_retries: int = 3,
        scoring: Optional[ScoringConfig] = None,
        grading: Optional[GradingConfig] = None,
        retry_policy: Optional[str] = None,
        retry_delay_ms: Optional[int] = None,
    ) -> None: ...
    @property
    def enabled(self) -> bool: ...
    @property
    def min_confidence(self) -> float: ...
    @property
    def max_retries(self) -> int: ...
    @property
    def scoring(self) -> Optional[ScoringConfig]: ...
    @property
    def grading(self) -> Optional[GradingConfig]: ...
    @property
    def retry_policy(self) -> Optional[str]: ...
    @property
    def retry_delay_ms(self) -> Optional[int]: ...
    def __repr__(self) -> str: ...

class NodeResult:
    """Result for a single node in an evaluation report."""
    @property
    def node_name(self) -> str: ...
    @property
    def score(self) -> float: ...
    @property
    def confidence(self) -> float: ...
    @property
    def retries(self) -> int: ...
    @property
    def issues(self) -> List[str]: ...
    @property
    def suggestions(self) -> List[str]: ...
    def __repr__(self) -> str: ...

class EvaluationReport:
    """Complete evaluation report extracted from agent state."""
    @staticmethod
    def from_state(state: SharedState) -> "EvaluationReport": ...
    @property
    def nodes(self) -> List[NodeResult]: ...
    @property
    def overall_score(self) -> float: ...
    @property
    def total_retries(self) -> int: ...
    @property
    def passed(self) -> bool: ...
    @property
    def timestamp(self) -> str: ...
    def save_json(self, path: str) -> None: ...
    def to_json(self) -> Any: ...
    def print(self) -> None: ...
    def print_summary(self) -> None: ...
    def __repr__(self) -> str: ...

# ─── Chunk Metadata ─────────────────────────────────────────────────────────

class ChunkMetadata:
    """Metadata for a text chunk produced by text splitters."""
    def __init__(
        self,
        source: Optional[str] = None,
        chunk_index: int = 0,
        start_char: int = 0,
        end_char: int = 0,
    ) -> None: ...
    @property
    def source(self) -> Optional[str]: ...
    @property
    def chunk_index(self) -> int: ...
    @property
    def start_char(self) -> int: ...
    @property
    def end_char(self) -> int: ...
    @property
    def extra(self) -> Dict[str, str]: ...
    def __repr__(self) -> str: ...

# ─── Retriever Strategy ─────────────────────────────────────────────────────

class RetrieverStrategy:
    """Strategy for document retrieval."""
    @staticmethod
    def semantic() -> "RetrieverStrategy": ...
    @staticmethod
    def hybrid(keyword_weight: float = 0.3) -> "RetrieverStrategy": ...
    @staticmethod
    def multiquery(variants: int = 3) -> "RetrieverStrategy": ...
    @staticmethod
    def decomposed(depth: int = 2) -> "RetrieverStrategy": ...
    @staticmethod
    def custom(chain_name: str) -> "RetrieverStrategy": ...
    def __repr__(self) -> str: ...

# ─── Rerank Strategy ────────────────────────────────────────────────────────

class RerankStrategy:
    """Strategy for re-ranking search results."""
    @staticmethod
    def none() -> "RerankStrategy": ...
    @staticmethod
    def llm() -> "RerankStrategy": ...
    @staticmethod
    def cross_encoder(model: str, endpoint: str) -> "RerankStrategy": ...
    @staticmethod
    def rrf(k: int = 60) -> "RerankStrategy": ...
    def __repr__(self) -> str: ...

# ─── Vector Store ────────────────────────────────────────────────────────────

class VectorStore:
    """Vector store wrapper for indexing and searching documents."""
    @staticmethod
    def in_memory(config: "RAGConfig") -> "VectorStore": ...
    def index_document(self, id: str, text: str, metadata: Dict[str, Any]) -> None: ...
    def search(self, query_embedding: List[float], top_k: int = 5) -> List["SearchResult"]: ...
    def delete(self, doc_id: str) -> None: ...
    def update(self, id: str, text: str) -> None: ...
    def get(self, doc_id: str) -> "Document": ...
    def list(self) -> List["Document"]: ...
    def clear(self) -> None: ...
    def __repr__(self) -> str: ...

# ─── Evaluation Utility ─────────────────────────────────────────────────────

def py_evaluate_output_score(output: Any, attempt: int) -> Tuple[float, str]:
    """Score an output for quality evaluation. Returns (score, feedback)."""
    ...
