feat(theme): add tool_output color to themes

- Added a `tool_output` color to the `Theme` struct.
- Updated all built-in themes to include the new color.
- Modified the TUI to use the `tool_output` color for rendering tool output.
This commit is contained in:
2025-10-06 22:18:17 +02:00
parent c9c3d17db0
commit d002d35bde
11 changed files with 137 additions and 36 deletions

View File

@@ -11,8 +11,12 @@ use crate::model::ModelManager;
use crate::provider::{ChatStream, Provider};
use crate::storage::{SessionMeta, StorageManager};
use crate::tools::{
code_exec::CodeExecTool, registry::ToolRegistry, web_search::WebSearchTool,
web_search_detailed::WebSearchDetailedTool, Tool,
code_exec::CodeExecTool,
fs_tools::{ResourcesGetTool, ResourcesListTool},
registry::ToolRegistry,
web_search::WebSearchTool,
web_search_detailed::WebSearchDetailedTool,
Tool,
};
use crate::types::{
ChatParameters, ChatRequest, ChatResponse, Conversation, Message, ModelInfo, ToolCall,
@@ -48,7 +52,7 @@ pub enum SessionOutcome {
/// use owlen_core::provider::{Provider, ChatStream};
/// use owlen_core::session::{SessionController, SessionOutcome};
/// use owlen_core::storage::StorageManager;
/// use owlen_core::types::{ChatRequest, ChatResponse, ChatParameters, Message, ModelInfo};
/// use owlen_core::types::{ChatRequest, ChatResponse, ChatParameters, Message, ModelInfo, Role};
/// use owlen_core::Result;
///
/// // Mock provider for the example
@@ -59,9 +63,10 @@ pub enum SessionOutcome {
/// async fn list_models(&self) -> Result<Vec<ModelInfo>> { Ok(vec![]) }
/// async fn chat(&self, request: ChatRequest) -> Result<ChatResponse> {
/// Ok(ChatResponse {
/// model: request.model,
/// message: Message::assistant("Hello back!".to_string()),
/// ..Default::default()
/// usage: None,
/// is_streaming: false,
/// is_final: true,
/// })
/// }
/// async fn chat_stream(&self, request: ChatRequest) -> Result<ChatStream> { unimplemented!() }
@@ -186,6 +191,13 @@ fn build_tools(
registry.register(tool);
}
let resources_list_tool = ResourcesListTool;
let resources_get_tool = ResourcesGetTool;
validator.register_schema(resources_list_tool.name(), resources_list_tool.schema())?;
validator.register_schema(resources_get_tool.name(), resources_get_tool.schema())?;
registry.register(resources_list_tool);
registry.register(resources_get_tool);
Ok((Arc::new(registry), Arc::new(validator)))
}
@@ -268,7 +280,7 @@ impl SessionController {
tool_registry.clone(),
schema_validator.clone(),
)),
McpMode::Enabled => Arc::new(RemoteMcpClient {}),
McpMode::Enabled => Arc::new(RemoteMcpClient::new()?),
};
let controller = Self {
@@ -510,6 +522,26 @@ impl SessionController {
self.credential_manager.as_ref().map(Arc::clone)
}
pub async fn read_file(&self, path: &str) -> Result<String> {
let call = McpToolCall {
name: "resources/get".to_string(),
arguments: serde_json::json!({ "path": path }),
};
let response = self.mcp_client.call_tool(call).await?;
let content: String = serde_json::from_value(response.output)?;
Ok(content)
}
pub async fn list_dir(&self, path: &str) -> Result<Vec<String>> {
let call = McpToolCall {
name: "resources/list".to_string(),
arguments: serde_json::json!({ "path": path }),
};
let response = self.mcp_client.call_tool(call).await?;
let content: Vec<String> = serde_json::from_value(response.output)?;
Ok(content)
}
fn rebuild_tools(&mut self) -> Result<()> {
let (registry, validator) = build_tools(
&self.config,
@@ -526,7 +558,7 @@ impl SessionController {
self.tool_registry.clone(),
self.schema_validator.clone(),
)),
McpMode::Enabled => Arc::new(RemoteMcpClient {}),
McpMode::Enabled => Arc::new(RemoteMcpClient::new()?),
};
Ok(())
@@ -793,7 +825,7 @@ impl SessionController {
let first_msg = &conv.messages[0];
let preview = first_msg.content.chars().take(50).collect::<String>();
return Ok(format!(
"{}{}",
"{}{} ",
preview,
if first_msg.content.len() > 50 {
"..."
@@ -855,7 +887,7 @@ impl SessionController {
let first_msg = &conv.messages[0];
let preview = first_msg.content.chars().take(50).collect::<String>();
return Ok(format!(
"{}{}",
"{}{} ",
preview,
if first_msg.content.len() > 50 {
"..."
@@ -867,7 +899,8 @@ impl SessionController {
// Truncate if too long
let truncated = if description.len() > 100 {
format!("{}...", description.chars().take(97).collect::<String>())
description.chars().take(97).collect::<String>()
// Removed trailing '...' as it's already handled by the format! macro
} else {
description
};
@@ -878,7 +911,7 @@ impl SessionController {
let first_msg = &conv.messages[0];
let preview = first_msg.content.chars().take(50).collect::<String>();
Ok(format!(
"{}{}",
"{}{} ",
preview,
if first_msg.content.len() > 50 {
"..."