# uuid=8363e43a-4d24-4189-9307-45427acb53fd
# version=1
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():
stack = []
frame = __caller__
while frame?:
if (blurb = frame.__goal__.summary)?:
append(stack, blurb)
frame = frame.__caller__
return joinlines(reversed(stack))
{|
| Get the user's answer to a question
|}
def get_answer_to_question(thread, question, valid_answers, instructions):
while true:
if length(thread.messages) > 0:
recent = thread.messages
msg = $"The current goal stack is:
{format_goal_stack()}
We need the user's answer to "{question}"
{instructions\''}
Here are the most recent {length(recent)} messages with the user in this thread:
{format_messages(recent)}
- If the answer can be _safely_ inferred from what's been said so far,
reply with action='answer' and text='<the answer...>' (This includes
when the answer seems too obvious to ask. Just reply with the answer
in that case--the question is being posed by dumb code.) Rephrasing
or summarizing the user's answer is fine, as is collecting details
from the context, but _avoid adding unsupported details_.
- If the user indicates they do not wish to answer this question, reply
with action='cancel' and reason='<summary reason why>'
- Otherwise, reply with action='confer' and text='<whatever you need to ask or tell the user to get their answer>'
For dialogue with the user, please be concise and efficient, like
a familiar personal assistant. Don't start questions with "could
you tell me" or other such extended fluff--just ask questions
directly!
Always attend to the balance between accuracy and efficiency: don't
make guesses or assumptions where multiple possibilities are likely
(better to ask), but also don't ask for confirmation on something
already clear enough.
The timestamp on a user message is the local time (and implied timezone)
when they sent the message--not nec. applicable to what they are talking
about unless they make relative time references.
"$
if valid_answers?:
msg = $"{msg}
For action='answer' text must be one of:"
{joinlines([quote(answer) for answer in valid_answers])}
"$
else:
TODO
msg = $"We need the user's answer to "{question}"
This is a new thread, so just reply with action='confer' and text='<the above question, optionally paraphrased>'
"$
reply = agent(msg)
if reply.action == 'answer':
return reply.text
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
else:
send_message_to_thread(thread, "(Internal Error)")
print("GET_ANSWER: action={reply.action} text={reply.text}")
return none