"""
CleverAgents LangGraph-based agent workflows.

This package contains all agent implementations using LangGraph for stateful
workflow orchestration and LangChain for LLM integration.

Available Agents
----------------
PlanGenerationGraph
    Generates code changes based on user prompts through a multi-stage workflow:
    load_context -> analyze_requirements -> generate_plan -> validate (with retry)

ContextAnalysisAgent
    Analyzes code context for relevance scoring and dependency mapping:
    load_files -> analyze_deps -> chunk_docs -> score_relevance -> summarize

AutoDebugAgent
    Analyzes errors, proposes fixes, validates them, and tracks attempts.

Interface Contract
------------------
All agents expose three methods:

- ``invoke(state, config)``: Synchronous execution for CLI commands, scripts
- ``ainvoke(state, config)``: Async execution for server endpoints
- ``stream(state, config)``: Streaming execution for real-time progress

Configuration
-------------
Always provide a ``thread_id`` for checkpoint isolation::

    config = {"configurable": {"thread_id": f"workflow-{uuid.uuid4()}"}}
    result = agent.invoke(state, config)

Testing Agents
--------------
Use LangChain's FakeListLLM for deterministic testing::

    from langchain_community.llms import FakeListLLM

    mock_llm = FakeListLLM(responses=[
        "Analysis result",
        "Generated code",
        "Validation passed",
    ])

    graph = PlanGenerationGraph(llm=mock_llm)

See Also
--------
- ADR-011: LangChain/LangGraph Integration
- https://python.langchain.com/docs/langgraph
"""


def __getattr__(name: str):
    """Lazy-load heavy graph classes on first attribute access.

    Importing the graph modules pulls in ``langchain``, ``langsmith``,
    and ``langgraph`` which adds ~1-2 s of import time.  By deferring
    these imports, ``from cleveragents.agents.base import Agent`` (used
    throughout the codebase) no longer triggers the heavy import chain,
    cutting per-subprocess CLI startup time significantly.
    """
    _GRAPH_IMPORTS: dict[str, tuple[str, str]] = {
        "AutoDebugAgent": (".graphs.auto_debug", "AutoDebugAgent"),
        "AutoDebugState": (".graphs.auto_debug", "AutoDebugState"),
        "ContextAnalysisAgent": (".graphs.context_analysis", "ContextAnalysisAgent"),
        "ContextAnalysisState": (".graphs.context_analysis", "ContextAnalysisState"),
        "PlanGenerationGraph": (".graphs.plan_generation", "PlanGenerationGraph"),
        "PlanGenerationState": (".graphs.plan_generation", "PlanGenerationState"),
    }
    if name in _GRAPH_IMPORTS:
        module_path, attr = _GRAPH_IMPORTS[name]
        import importlib

        mod = importlib.import_module(module_path, __name__)
        value = getattr(mod, attr)
        # Cache on the module to avoid repeated imports
        globals()[name] = value
        return value
    raise AttributeError(f"module {__name__!r} has no attribute {name!r}")


__all__ = [
    "AutoDebugAgent",
    "AutoDebugState",
    "ContextAnalysisAgent",
    "ContextAnalysisState",
    "PlanGenerationGraph",
    "PlanGenerationState",
]
