# uuid=8363e43a-4d24-4189-9307-45427acb53fd

if version\0 < 1:

    from channels import send_message_to_thread, wait_for_new_messages_on_thread, format_messages
    from llm      import agent

    {|
     | Returns a multi-line string describing the current goal stack.
     |
     | Each frame has a __caller__ which is the frame that invoked it.
     | And each frame has a __goal__ which is the goal that owns it.
     | And each goal optionally has a summary, which we collect here.
     |}
    def format_goal_stack():
        return joinlines(goal_stack())

    def goal_stack():
        stack = []
        frame = __caller__
        while frame?:
            if (blurb = frame.__goal__.summary)?:
                append(stack, blurb)
            frame = frame.__caller__
        return reversed(stack)

    (|
     | Answer a question
     |
     | (Avoiding doc string here so "answer_question" doesn't become the top goal.)
     |)
    def answer_question(thread, user, instructions, sofar, answer_eg, more_actions):
        username = user.name
        while true:
            recent = thread.messages
            goals  = goal_stack()
            msg = $"The current goal stack is:
                        {joinlines(goals)}

                    Immediate goal:
                         {goals[-1]}

                    General context:
                        {user.context}
                        We are having a private chat with {username}

                    Here are the messages in the thread.  Each timestamp is when the message was sent:
                        {format_messages(recent)}

                    {if sofar? then
                    "So far we have determined:
                         {sofar}
                     " else ''
                    }
                    Instructions:
                        {instructions\''}
                        - If there is ambiguity you can't resolve, ask {username}.  Using inference
                            is ok (dog -> animal), but DO NOT FILL IN BLANKS WITH GUESSES (animal -> dog).
                        - In any user dialog, be concise like a familiar PA.  No fluff like "could you
                            please".  But also don't pester: if they gave an answer, use it.
                        - Detail your answer in your reason field and double check your reasoning
                            for accuracy and completeness before answering.  (Make sure: you
                            aren't making claims beyond what {username} stated, and conversely
                            that you aren't about to ask a question that {username} has already
                            answered.)

                    Possible Actions:

                        If {username} indicates they want to abandon this pursuit, reply:
                            action="cancel",
                            text="<brief reason>"

                        If you have all the information you need, reply, e.g.:
                            action="answer",
                            answer={answer_eg}

                        {more_actions\''}If you need more information, reply:
                            action="confer",
                            text="<your concise question(s) for {username}>"
                    "$

            n0    = length(thread.messages)
            reply = agent(msg)
            sleep(0)    -- at the moment agent is synchronous, so we need to give channel tasks a moment to run
            if length(thread.messages) > n0:
                print("WARNING: New message came in while thinking.  Re-thinking...")
                continue while

            if reply.action == 'answer':
                return reply.answer

            else if reply.action == 'confer':
                send_message_to_thread(thread, reply.text)
                wait_for_new_messages_on_thread(thread)

            else if reply.action == 'cancel':
                send_message_to_thread(thread, "(Aborting)")
                print("Canceling this question because {reply.text}")
                return none -- probably should raise

            else:
                send_message_to_thread(thread, "(Internal Error)")
                print("enumerate_foods: Badly formatted reply")
                pprint(reply)
                return none -- probably should raise