in crates/q_chat/src/conversation_state.rs [770:856]
fn assert_conversation_state_invariants(state: FigConversationState, assertion_iteration: usize) {
if let Some(Some(msg)) = state.history.as_ref().map(|h| h.first()) {
assert!(
matches!(msg, ChatMessage::UserInputMessage(_)),
"{assertion_iteration}: First message in the history must be from the user, instead found: {:?}",
msg
);
}
if let Some(Some(msg)) = state.history.as_ref().map(|h| h.last()) {
assert!(
matches!(msg, ChatMessage::AssistantResponseMessage(_)),
"{assertion_iteration}: Last message in the history must be from the assistant, instead found: {:?}",
msg
);
// If the last message from the assistant contains tool uses, then the next user
// message must contain tool results.
match (state.user_input_message.user_input_message_context.as_ref(), msg) {
(
Some(ctx),
ChatMessage::AssistantResponseMessage(AssistantResponseMessage {
tool_uses: Some(tool_uses),
..
}),
) if !tool_uses.is_empty() => {
assert!(
ctx.tool_results.as_ref().is_some_and(|r| !r.is_empty()),
"The user input message must contain tool results when the last assistant message contains tool uses"
);
},
_ => {},
}
}
if let Some(history) = state.history.as_ref() {
for (i, msg) in history.iter().enumerate() {
// User message checks.
if let ChatMessage::UserInputMessage(user) = msg {
assert!(
user.user_input_message_context
.as_ref()
.is_none_or(|ctx| ctx.tools.is_none()),
"the tool specification should be empty for all user messages in the history"
);
// Check that messages with tool results are immediately preceded by an
// assistant message with tool uses.
if user
.user_input_message_context
.as_ref()
.is_some_and(|ctx| ctx.tool_results.as_ref().is_some_and(|r| !r.is_empty()))
{
match history.get(i.checked_sub(1).unwrap_or_else(|| {
panic!(
"{assertion_iteration}: first message in the history should not contain tool results"
)
})) {
Some(ChatMessage::AssistantResponseMessage(assistant)) => {
assert!(assistant.tool_uses.is_some());
},
_ => panic!(
"expected an assistant response message with tool uses at index: {}",
i - 1
),
}
}
}
}
}
let actual_history_len = state.history.unwrap_or_default().len();
assert!(
actual_history_len <= MAX_CONVERSATION_STATE_HISTORY_LEN,
"history should not extend past the max limit of {}, instead found length {}",
MAX_CONVERSATION_STATE_HISTORY_LEN,
actual_history_len
);
let ctx = state
.user_input_message
.user_input_message_context
.as_ref()
.expect("user input message context must exist");
assert!(
ctx.tools.is_some(),
"Currently, the tool spec must be included in the next user message"
);
}