# =============================================================================
# MANUAL SEED OVERRIDES
# =============================================================================
# This file contains hand-curated extras and configuration that should NOT be
# overwritten by `just seed`. The seed_generator merges this file into the
# auto-generated seed.toml via the --merge flag.
#
# Sections:
#   [renames]         - Builder name overrides (e.g. LlmAgent -> Agent)
#   [[builders.X.extras]] - Manual extra methods per builder
#   [[manual_exports]] - Extra imports appended to __init__.py
#

# ---------------------------------------------------------------------------
# FIELD DOCSTRINGS
# ---------------------------------------------------------------------------
# Override auto-generated field docstrings in builders and .pyi stubs.
# Keys are field names (or alias names); values are the docstring text.

[field_docs]
output_schema = """Force the LLM to respond with structured JSON matching a Pydantic model.

When set, the agent replies **only** with JSON data conforming to
this schema. The agent **cannot use tools** while ``output_schema``
is active.

.. note::

   Prefer ``.returns(Model)`` or ``@ Model`` over this method.
   ``.returns()`` sets the same ADK constraint AND automatically
   parses the response in ``.ask()`` calls. This method sets the
   raw ADK field without automatic parsing.

   - ``.returns(Model)`` / ``@ Model`` → LLM constraint + parsing
   - ``.output_schema(Model)`` → LLM constraint only (raw field)
   - ``.writes(key)`` → stores text in state (no format constraint)
   - ``.produces(Model)`` → contract annotation (no runtime effect)
"""
input_schema = """Schema defining the expected input structure when this agent is invoked as a tool by another agent.

When another agent invokes this agent via ``AgentTool``, the calling
agent's arguments are validated against this Pydantic model. Irrelevant
for top-level agents — only for agents that serve as tools.

.. note::

   Prefer ``.accepts(Model)`` over this method for clarity.
   ``.accepts()`` is the recommended alias on BuilderBase.

   - ``.accepts(Model)`` → tool-mode input validation (same as this)
   - ``.consumes(Model)`` → contract annotation (no runtime effect)
"""
output_key = "Session state key where the agent's response text is stored. Downstream agents and state transforms can read this key. Alias: ``.save_as(key)`` / ``.writes(key)``."
save_as = "Session state key where the agent's response text is stored. Downstream agents and state transforms can read this key via ``state['key']``. Alias for ``output_key``. Prefer ``.writes(key)``."
disallow_transfer_to_parent = "Prevent this agent from transferring control back to its parent. Also forces a handoff back to parent on the next turn, preventing the user from getting stuck. See also ``.isolate()``."
disallow_transfer_to_peers = "Prevent this agent from transferring control to sibling agents. See also ``.isolate()``."

# ---------------------------------------------------------------------------
# BUILDER RENAMES
# ---------------------------------------------------------------------------
# Maps ADK class names to friendlier builder names.
[renames]
LlmAgent = "Agent"
SequentialAgent = "Pipeline"
ParallelAgent = "FanOut"
LoopAgent = "Loop"

# ---------------------------------------------------------------------------
# OPTIONAL CONSTRUCTOR ARGS
# ---------------------------------------------------------------------------
# These add optional positional params to __init__:
#   Agent("name", "model") works alongside Agent("name").model("model")

[builders.Agent]
optional_constructor_args = ["model"]

# New aliases added via merge into auto-generated aliases
[builders.Agent.manual_aliases]
save_as = "output_key"

# Deprecated aliases — still work but emit DeprecationWarning
[builders.Agent.deprecated_aliases]
outputs = { field = "output_key", use = "save_as" }
history = { field = "include_contents", use = "context" }
include_history = { field = "include_contents", use = "context" }
static_instruct = { field = "static_instruction", use = "static" }

# ---------------------------------------------------------------------------
# AGENT EXTRAS (Phase 1)
# ---------------------------------------------------------------------------

[[builders.Agent.extras]]
name = "tool"
signature = "(self, fn_or_tool: Any, *, require_confirmation: bool = False) -> Self"
doc = "Add a single tool (appends). Wraps plain callables in FunctionTool when require_confirmation=True."
behavior = "runtime_helper"
helper_func = "_add_tool"
example = '''
def search(query: str) -> str:
    """Search the web."""
    return f"Results for {query}"

agent = Agent("helper").tool(search).build()
'''
see_also = ["FunctionTool", "Agent.guardrail"]

[[builders.Agent.extras]]
name = "guardrail"
signature = "(self, fn: Callable[..., Any]) -> Self"
doc = "Attach a guardrail function as both before_model and after_model callback."
behavior = "dual_callback"
target_fields = ["before_model_callback", "after_model_callback"]
example = '''
def safety_check(callback_context, llm_request, llm_response, agent):
    if "unsafe" in str(llm_response):
        return None  # Block response
    return llm_response

agent = Agent("safe", "gemini-2.5-flash").guardrail(safety_check).build()
'''
see_also = ["Agent.before_model", "Agent.after_model"]

[[builders.Agent.extras]]
name = "ask"
signature = "(self, prompt: str) -> str"
doc = "One-shot execution. Build agent, send prompt, return response text."
behavior = "runtime_helper"
helper_func = "run_one_shot"
example = '''
reply = Agent("qa", "gemini-2.5-flash").instruct("Answer questions.").ask("What is Python?")
print(reply)
'''
see_also = ["Agent.ask_async", "Agent.stream"]

[[builders.Agent.extras]]
name = "ask_async"
signature = "(self, prompt: str) -> str"
doc = "Async one-shot execution."
behavior = "runtime_helper_async"
helper_func = "run_one_shot_async"

[[builders.Agent.extras]]
name = "stream"
signature = "(self, prompt: str) -> AsyncIterator[str]"
doc = "Streaming execution. Yields response text chunks."
behavior = "runtime_helper_async_gen"
helper_func = "run_stream"
example = '''
async for chunk in Agent("writer", "gemini-2.5-flash").instruct("Write a poem.").stream("About the sea"):
    print(chunk, end="")
'''
see_also = ["Agent.ask", "Agent.events"]

[[builders.Agent.extras]]
name = "test"
signature = "(self, prompt: str, *, contains: str | None = None, matches: str | None = None, equals: str | None = None) -> Self"
doc = "Run a smoke test. Calls .ask() internally, asserts output matches condition."
behavior = "runtime_helper"
helper_func = "run_inline_test"

[[builders.Agent.extras]]
name = "session"
signature = "(self) -> Any"
doc = "Create an interactive session context manager. Use with 'async with'."
behavior = "runtime_helper_ctx"
helper_func = "create_session"

[[builders.Agent.extras]]
name = "map"
signature = "(self, prompts: list[str], *, concurrency: int = 5) -> list[str]"
doc = "Run agent against multiple prompts with bounded concurrency."
behavior = "runtime_helper"
helper_func = "run_map"

[[builders.Agent.extras]]
name = "map_async"
signature = "(self, prompts: list[str], *, concurrency: int = 5) -> list[str]"
doc = "Async batch execution against multiple prompts."
behavior = "runtime_helper_async"
helper_func = "run_map_async"

[[builders.Agent.extras]]
name = "events"
signature = "(self, prompt: str) -> AsyncIterator[Any]"
doc = "Stream raw ADK Event objects. Yields every event including state deltas and function calls."
behavior = "runtime_helper_async_gen"
helper_func = "run_events"

# ---------------------------------------------------------------------------
# CONTEXT ENGINEERING EXTRAS (Phase 5.1)
# ---------------------------------------------------------------------------

[[builders.Agent.extras]]
name = "context"
signature = "(self, spec: Any) -> Self"
doc = "Declare what conversation context this agent should see. Accepts a C module transform (C.none(), C.user_only(), C.from_state(), etc.)."
behavior = "field_set"
target_field = "_context_spec"
example = '''
from adk_fluent import C

agent = (
    Agent("writer")
    .model("gemini-2.5-flash")
    .instruct("Write about {topic}.")
    .context(C.from_state("topic"))
    .build()
)
'''
see_also = ["C", "Agent.memory"]

[[builders.Agent.extras]]
name = "show"
signature = "(self) -> Self"
doc = "Force this agent's events to be user-facing (override topology inference)."
behavior = "runtime_helper_ctx"
helper_func = "_show_agent"
example = '''
# Force intermediate agent output to be visible to users
agent = Agent("logger").model("m").instruct("Log progress.").show()
'''
see_also = ["Agent.hide"]

[[builders.Agent.extras]]
name = "hide"
signature = "(self) -> Self"
doc = "Force this agent's events to be internal (override topology inference)."
behavior = "runtime_helper_ctx"
helper_func = "_hide_agent"
example = '''
# Suppress terminal agent output from user view
agent = Agent("cleanup").model("m").instruct("Clean up.").hide()
'''
see_also = ["Agent.show"]

[[builders.Agent.extras]]
name = "memory"
signature = "(self, mode: str = 'preload') -> Self"
doc = "Add memory tools to this agent. Modes: 'preload', 'on_demand', 'both'."
behavior = "runtime_helper"
helper_func = "_add_memory"
example = '''
agent = Agent("assistant", "gemini-2.5-flash").memory("preload").build()
'''
see_also = ["Agent.memory_auto_save", "Agent.context"]

[[builders.Agent.extras]]
name = "memory_auto_save"
signature = "(self) -> Self"
doc = "Auto-save session to memory after each agent run."
behavior = "runtime_helper_ctx"
helper_func = "_add_memory_auto_save"

# ---------------------------------------------------------------------------
# DELEGATION EXTRAS
# ---------------------------------------------------------------------------

[[builders.Agent.extras]]
name = "delegate"
signature = "(self, agent: Any) -> Self"
doc = "Add an agent as a delegatable tool (wraps in AgentTool). The coordinator LLM can route to this agent."
behavior = "runtime_helper"
helper_func = "delegate_agent"
example = '''
specialist = Agent("invoice_parser", "gemini-2.5-flash").instruct("Parse invoices.")
coordinator = (
    Agent("router", "gemini-2.5-flash")
    .instruct("Route tasks to specialists.")
    .delegate(specialist)
    .build()
)
'''
see_also = ["Agent.tool", "Agent.isolate"]

# ---------------------------------------------------------------------------
# TRANSFER CONTROL EXTRAS
# ---------------------------------------------------------------------------

[[builders.Agent.extras]]
name = "isolate"
signature = "(self) -> Self"
doc = "Prevent this agent from transferring to parent or peers. Sets both disallow_transfer_to_parent and disallow_transfer_to_peers to True. Use for specialist agents that should complete their task and return."
behavior = "runtime_helper"
helper_func = "_isolate_agent"
example = '''
# Specialist agent that completes its task without transferring
specialist = (
    Agent("invoice_parser", "gemini-2.5-flash")
    .instruct("Parse the invoice and extract line items.")
    .isolate()
    .output_schema(Invoice)
    .build()
)
'''
see_also = ["Agent.disallow_transfer_to_parent", "Agent.disallow_transfer_to_peers"]

[[builders.Agent.extras]]
name = "stay"
signature = "(self) -> Self"
doc = "Prevent this agent from transferring back to its parent. Use for agents that should complete their work before returning."
behavior = "runtime_helper"
helper_func = "_stay_agent"
example = '''
specialist = (
    Agent("invoice_parser", "gemini-2.5-flash")
    .instruct("Parse the invoice.")
    .stay()  # Must finish before returning to coordinator
    .build()
)
'''
see_also = ["Agent.isolate", "Agent.no_peers"]

[[builders.Agent.extras]]
name = "no_peers"
signature = "(self) -> Self"
doc = "Prevent this agent from transferring to sibling agents. The agent can still return to its parent."
behavior = "runtime_helper"
helper_func = "_no_peers_agent"
example = '''
focused = (
    Agent("researcher", "gemini-2.5-flash")
    .instruct("Research the topic thoroughly.")
    .no_peers()  # Don't hand off to sibling agents
    .build()
)
'''
see_also = ["Agent.isolate", "Agent.stay"]

# ---------------------------------------------------------------------------
# SCHEMA EXTRAS
# ---------------------------------------------------------------------------

[[builders.Agent.extras]]
name = "tool_schema"
signature = "(self, schema: type) -> Self"
doc = "Attach a ToolSchema declaring tool state dependencies."
behavior = "field_set"
target_field = "_tool_schema"

[[builders.Agent.extras]]
name = "callback_schema"
signature = "(self, schema: type) -> Self"
doc = "Attach a CallbackSchema declaring callback state dependencies."
behavior = "field_set"
target_field = "_callback_schema"

[[builders.Agent.extras]]
name = "prompt_schema"
signature = "(self, schema: type) -> Self"
doc = "Attach a PromptSchema declaring prompt state dependencies."
behavior = "field_set"
target_field = "_prompt_schema"

# ---------------------------------------------------------------------------
# IR CONVERSION EXTRAS
# ---------------------------------------------------------------------------
# These wire to_ir() through the codegen so it survives regeneration.

[[builders.Agent.extras]]
name = "to_ir"
signature = "(self) -> Any"
doc = "Convert this Agent builder to an AgentNode IR node."
behavior = "runtime_helper_ctx"
helper_func = "_agent_to_ir"

[[builders.Pipeline.extras]]
name = "to_ir"
signature = "(self) -> Any"
doc = "Convert this Pipeline builder to a SequenceNode IR node."
behavior = "runtime_helper_ctx"
helper_func = "_pipeline_to_ir"

[[builders.FanOut.extras]]
name = "to_ir"
signature = "(self) -> Any"
doc = "Convert this FanOut builder to a ParallelNode IR node."
behavior = "runtime_helper_ctx"
helper_func = "_fanout_to_ir"

[[builders.Loop.extras]]
name = "to_ir"
signature = "(self) -> Any"
doc = "Convert this Loop builder to a LoopNode IR node."
behavior = "runtime_helper_ctx"
helper_func = "_loop_to_ir"
