···1515};
1616use crate::http_client::HttpClient;
1717use crate::llm::base::{
1818- ChatHistoryContent, ContentType, ReasoningConfig, ToolCallRequest, ToolCallResponse, USER_ROLE,
1818+ ChatHistoryContent, ContentType, MessageRole, ReasoningConfig, ToolCallRequest,
1919+ ToolCallResponse,
1920};
2021use crate::llm::tools::{
2122 ANTHROPIC_SCHEMA_KEY, SerializedTool, get_owned_tools, process_tool_calls,
···2728#[derive(Clone, Serialize)]
2829pub(crate) struct AnthropicChatHistoryItem {
2930 /// Either "user" or "assistant".
3030- pub role: String,
3131+ pub role: MessageRole,
3132 /// The contents of this item.
3233 pub content: Vec<AnthropicResponseContent>,
3334}
34353536impl From<ChatHistoryItem> for AnthropicChatHistoryItem {
3637 fn from(value: ChatHistoryItem) -> Self {
3737- let role = value.role.clone();
3838+ let role = value.role;
3839 Self {
3940 content: value
4041 .content
···116117 .collect();
117118118119 messages.push(AnthropicChatHistoryItem {
119119- role: USER_ROLE.to_owned(),
120120+ role: MessageRole::User,
120121 content: vec![req.message.clone().into()],
121122 });
122123···239240 /// The model that generated the response
240241 pub(crate) model: String,
241242 /// The role of the message (usually "assistant")
242242- pub(crate) role: String,
243243+ pub(crate) role: MessageRole,
243244 /// Why the model stopped generating (e.g., "end_turn")
244245 pub(crate) stop_reason: String,
245246 /// The stop sequence that caused generation to end, if any
···373374374375 // Append the contents
375376 chat_history.push(AnthropicChatHistoryItem {
376376- role: "assistant".into(),
377377+ role: MessageRole::Assistant,
377378 content: response.content.clone(),
378379 });
379380···408409409410 // Append the new response to chat history
410411 chat_history.push(AnthropicChatHistoryItem {
411411- role: "assistant".into(),
412412+ role: MessageRole::Assistant,
412413 content: response.content.clone(),
413414 });
414415···460461 use crate::http_client::{MockHttpClient, ReqwestClient, SequentialMockHttpClient};
461462 use crate::llm::anthropic::{AnthropicTextResponseContent, DEFAULT_CLAUDE_MODEL};
462463 use crate::llm::base::{
463463- ApiClient, ChatHistoryContent, ChatHistoryItem, ChatRequest, ContentType, ToolCallResponse,
464464- USER_ROLE,
464464+ ApiClient, ChatHistoryContent, ChatHistoryItem, ChatRequest, ContentType, MessageRole,
465465+ ToolCallResponse,
465466 };
466467 use crate::llm::tools::test_utils::MockTool;
467468···494495 let mock_response = AnthropicResponse {
495496 id: "mock-id".to_string(),
496497 model: DEFAULT_CLAUDE_MODEL.to_string(),
497497- role: "assistant".to_string(),
498498+ role: MessageRole::Assistant,
498499 stop_reason: "end_turn".to_string(),
499500 stop_sequence: None,
500501 usage: AnthropicUsageStats {
···573574 let tool_call_response = AnthropicResponse {
574575 id: "msg-1".into(),
575576 model: DEFAULT_CLAUDE_MODEL.into(),
576576- role: "assistant".into(),
577577+ role: MessageRole::Assistant,
577578 stop_reason: "tool_use".into(),
578579 stop_sequence: None,
579580 usage: AnthropicUsageStats {
···596597 let text_response = AnthropicResponse {
597598 id: "msg-2".into(),
598599 model: DEFAULT_CLAUDE_MODEL.into(),
599599- role: "assistant".into(),
600600+ role: MessageRole::Assistant,
600601 stop_reason: "end_turn".into(),
601602 stop_sequence: None,
602603 usage: AnthropicUsageStats {
···702703 let second_message = ChatRequest {
703704 chat_history: vec![
704705 ChatHistoryItem {
705705- role: USER_ROLE.into(),
706706+ role: MessageRole::User,
706707 content: vec![ChatHistoryContent::Text(first_message.message.clone())],
707708 },
708709 chat_history_contents,
+13-6
zqa-rag/src/llm/base.rs
···88use super::errors::LLMError;
99use crate::llm::tools::{CallbackFn, Tool};
10101111-/// The user role.
1212-pub const USER_ROLE: &str = "user";
1313-/// The assistant role.
1414-pub const ASSISTANT_ROLE: &str = "assistant";
1111+/// Roles for messages
1212+#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
1313+#[serde(rename_all = "lowercase")]
1414+pub enum MessageRole {
1515+ /// A user message/response. Some providers fold tool responses into this.
1616+ User,
1717+ /// An assistant response.
1818+ Assistant,
1919+ /// Some providers, like OpenRouter, use a separate role for tool responses.
2020+ Tool,
2121+}
15221623/// A user-facing, generic, tool call request. This contains the tool name and the parameters
1724/// passed to that tool. It also includes the tool call id, which most providers use to
···6471pub struct ChatHistoryItem {
6572 /// The chat role. Every supported provider has a "user" (`USER_ROLE`) and an "assistant"
6673 /// (`ASSISTANT_ROLE`) role.
6767- pub role: String,
7474+ pub role: MessageRole,
6875 /// The contents of this item. This is a `Vec` because some APIs expect tool call requests to
6976 /// be bundled together with the text preceding it.
7077 pub content: Vec<ChatHistoryContent>,
···9198 .collect();
929993100 Self {
9494- role: ASSISTANT_ROLE.into(),
101101+ role: MessageRole::Assistant,
95102 content,
96103 }
97104 }