# Copyright (c) Microsoft. All rights reserved.
import asyncio
from typing import Annotated

from semantic_kernel.agents import AgentRegistry, OpenAIAssistantAgent
from semantic_kernel.functions import kernel_function

"""
The following sample demonstrates how to create an OpenAI Assistant agent that answers
questions about a sample menu using a Semantic Kernel Plugin. The agent is created
using a yaml declarative spec.
"""

# Simulate a conversation with the agent
USER_INPUTS = [
    "Hello",
    "What is the special soup?",
    "How much does that cost?",
    "Thank you",
]

# Define the YAML string for the sample
SPEC = """
type: openai_assistant
name: Host
instructions: Respond politely to the user's questions.
model:
  id: ${OpenAI:ChatModelId}
tools:
  - id: MenuPlugin.get_specials
    type: function
  - id: MenuPlugin.get_item_price
    type: function
"""


# Define a sample plugin for the sample
class MenuPlugin:
    """A sample Menu Plugin used for the concept sample."""

    @kernel_function(description="Provides a list of specials from the menu.")
    def get_specials(self) -> Annotated[str, "Returns the specials from the menu."]:
        return """
        Special Soup: Clam Chowder
        Special Salad: Cobb Salad
        Special Drink: Chai Tea
        """

    @kernel_function(description="Provides the price of the requested menu item.")
    def get_item_price(
        self, menu_item: Annotated[str, "The name of the menu item."]
    ) -> Annotated[str, "Returns the price of the menu item."]:
        return "$9.99"


async def main():
    # 1. Create the client using Azure OpenAI resources and configuration
    client = OpenAIAssistantAgent.create_client()

    # 2. Create the assistant on the Azure OpenAI service
    agent: OpenAIAssistantAgent = await AgentRegistry.create_from_yaml(
        SPEC,
        plugins=[MenuPlugin()],
        client=client,
    )

    # 3. Create a thread for the agent
    # If no thread is provided, a new thread will be
    # created and returned with the initial response
    thread = None

    try:
        for user_input in USER_INPUTS:
            print(f"# User: {user_input}")
            # 4. Invoke the agent for the specified thread for response
            async for response in agent.invoke(
                messages=user_input,
                thread=thread,
            ):
                print(f"# {response.name}: {response}")
                thread = response.thread
    finally:
        # 5. Clean up the resources
        await thread.delete() if thread else None
        await agent.client.beta.assistants.delete(assistant_id=agent.id)

    """
    Sample Output:

    # User: Hello
    # Agent: Hello! How can I assist you today?
    # User: What is the special soup?
    # ...
    """


if __name__ == "__main__":
    asyncio.run(main())
