From de0e665f573deaba65972b60b604a7b28586deca Mon Sep 17 00:00:00 2001 From: milan Date: Sun, 24 May 2026 21:10:10 +0200 Subject: [PATCH] update formatting restructure project add cancellation token to cancel mcp server collection from serving --- .gitignore | 2 +- Cargo.lock => cli/Cargo.lock | 3 +- Cargo.toml => cli/Cargo.toml | 11 +++--- {src => cli/src}/config.rs | 0 {src => cli/src}/human_interface/audio.rs | 0 {src => cli/src}/human_interface/cli.rs | 0 {src => cli/src}/human_interface/mod.rs | 0 {src => cli/src}/i18n/mod.rs | 0 {src => cli/src}/i18n/translations/de.json | 0 {src => cli/src}/main.rs | 3 +- {src => cli/src}/model.rs | 0 mcp_server_collection/src/caldav/mod.rs | 40 ++++++++++++++-------- mcp_server_collection/src/lib.rs | 15 +++++--- mcp_server_collection/src/main.rs | 2 +- own_mcp/src/mcp/chat.rs | 6 ++-- 15 files changed, 53 insertions(+), 29 deletions(-) rename Cargo.lock => cli/Cargo.lock (99%) rename Cargo.toml => cli/Cargo.toml (66%) rename {src => cli/src}/config.rs (100%) rename {src => cli/src}/human_interface/audio.rs (100%) rename {src => cli/src}/human_interface/cli.rs (100%) rename {src => cli/src}/human_interface/mod.rs (100%) rename {src => cli/src}/i18n/mod.rs (100%) rename {src => cli/src}/i18n/translations/de.json (100%) rename {src => cli/src}/main.rs (97%) rename {src => cli/src}/model.rs (100%) diff --git a/.gitignore b/.gitignore index 40cb351..aac20bb 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,5 @@ assist.toml server.toml temporary_audio -src/human_interface/.AUTH_HEADER +cli/src/human_interface/.AUTH_HEADER .idea diff --git a/Cargo.lock b/cli/Cargo.lock similarity index 99% rename from Cargo.lock rename to cli/Cargo.lock index 4596900..7596ca4 100644 --- a/Cargo.lock +++ b/cli/Cargo.lock @@ -1921,7 +1921,7 @@ dependencies = [ ] [[package]] -name = "own_assist" +name = "own_assist_cli" version = "0.3.0" dependencies = [ "base64", @@ -1940,6 +1940,7 @@ dependencies = [ "serde", "thiserror 2.0.18", "tokio", + "tokio-util", "url", ] diff --git a/Cargo.toml b/cli/Cargo.toml similarity index 66% rename from Cargo.toml rename to cli/Cargo.toml index 5465a7a..c9d99fd 100644 --- a/Cargo.toml +++ b/cli/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "own_assist" +name = "own_assist_cli" version = "0.3.0" edition = "2024" @@ -10,9 +10,9 @@ rmcp = { version = "1.3.0", features = ["client"] } log = { version = "0.4.29" } serde = { version = "1.0.228", features = ["derive"] } url = "2.5.8" -own_mcp = { path = "own_mcp" } -own_assist_common = { path = "common" } -mcp_server_collection = { path = "mcp_server_collection", optional = true} +own_mcp = { path = "../own_mcp" } +own_assist_common = { path = "../common" } +mcp_server_collection = { path = "../mcp_server_collection", optional = true} thiserror = "2.0.18" dialoguer = "0.12.0" indicatif = "0.18.4" @@ -21,7 +21,8 @@ clap = { version = "4.6.0", features = ["derive"] } base64 = "0.22.1" cpal = "0.17.3" rodio = "0.22.2" +tokio-util = { version = "0.7.18", optional = true } [features] default = ["built-in-mcp-collection"] -built-in-mcp-collection = ["dep:mcp_server_collection"] \ No newline at end of file +built-in-mcp-collection = ["dep:mcp_server_collection", "dep:tokio-util"] \ No newline at end of file diff --git a/src/config.rs b/cli/src/config.rs similarity index 100% rename from src/config.rs rename to cli/src/config.rs diff --git a/src/human_interface/audio.rs b/cli/src/human_interface/audio.rs similarity index 100% rename from src/human_interface/audio.rs rename to cli/src/human_interface/audio.rs diff --git a/src/human_interface/cli.rs b/cli/src/human_interface/cli.rs similarity index 100% rename from src/human_interface/cli.rs rename to cli/src/human_interface/cli.rs diff --git a/src/human_interface/mod.rs b/cli/src/human_interface/mod.rs similarity index 100% rename from src/human_interface/mod.rs rename to cli/src/human_interface/mod.rs diff --git a/src/i18n/mod.rs b/cli/src/i18n/mod.rs similarity index 100% rename from src/i18n/mod.rs rename to cli/src/i18n/mod.rs diff --git a/src/i18n/translations/de.json b/cli/src/i18n/translations/de.json similarity index 100% rename from src/i18n/translations/de.json rename to cli/src/i18n/translations/de.json diff --git a/src/main.rs b/cli/src/main.rs similarity index 97% rename from src/main.rs rename to cli/src/main.rs index 68562d8..fb6fca8 100644 --- a/src/main.rs +++ b/cli/src/main.rs @@ -14,6 +14,7 @@ use own_assist_common::config_loader::ConfigLoadingError; use own_assist_common::{exit_msg, init_tracing_subscriber}; use own_mcp::AgentChat; use tokio::task::JoinHandle; +use tokio_util::sync::CancellationToken; /// partial mcp client with cli and voice interaction #[derive(Parser, Debug)] @@ -67,7 +68,7 @@ async fn chat_loop(mut human_interface: impl HumanInterface, mut agent_chat: Age } #[cfg(feature = "built-in-mcp-collection")] -fn launch_mcp_server() -> Result, ConfigLoadingError> { +fn launch_mcp_server() -> Result, ConfigLoadingError> { let config = mcp_server_collection::config::Config::from_file()?; let handle = tokio::task::spawn(mcp_server_collection::serve(config)); diff --git a/src/model.rs b/cli/src/model.rs similarity index 100% rename from src/model.rs rename to cli/src/model.rs diff --git a/mcp_server_collection/src/caldav/mod.rs b/mcp_server_collection/src/caldav/mod.rs index 90cec72..c5e7b5c 100644 --- a/mcp_server_collection/src/caldav/mod.rs +++ b/mcp_server_collection/src/caldav/mod.rs @@ -1,12 +1,12 @@ -use tracing::Level; -use chrono::{Duration, Local}; use crate::caldav::client::{ AuthorizedCaldavClient, find_calendars, get_caldav_client, get_components, upload_components, }; +use crate::caldav::event::McpEvent; use crate::caldav::todo::McpTodo; use crate::server_handler::{ McpServerHandler, McpServerHandlerError, get_additional_property, get_property_as_string, }; +use chrono::{Duration, Local}; use http::Uri; use icalendar::{Event, EventLike, Todo}; use libdav::dav::FoundCollection; @@ -19,7 +19,7 @@ use serde::Deserialize; use std::str::FromStr; use toml::Value; use toml::map::Map; -use crate::caldav::event::McpEvent; +use tracing::Level; mod client; mod datetime_conversion; @@ -193,8 +193,11 @@ impl CalDavHandler { } #[tool(description = "gets events of next 7 days")] - async fn get_upcoming_events(&self, parameters: Parameters) -> Result { - const DAYS_DELTA: Duration = Duration::days(7); + async fn get_upcoming_events( + &self, + parameters: Parameters, + ) -> Result { + const DAYS_DELTA: Duration = Duration::days(7); const RECURRENCE_LIMIT: u16 = 10; let calendar = self.get_calendar_by_name(parameters.0.calendar_name)?; @@ -203,7 +206,7 @@ impl CalDavHandler { let mut events: Vec = Vec::new(); for component in components { - if let Some(event_component) = component.as_event() { + if let Some(event_component) = component.as_event() { let event: McpEvent = event_component.clone().try_into()?; let lower_bound = Local::now().with_timezone(&icalendar::Tz::Local(Local)); @@ -212,28 +215,37 @@ impl CalDavHandler { match recurrence { Ok(recurrence) => { - let recurrence_result = recurrence.after(lower_bound).before(upper_bound).all(RECURRENCE_LIMIT); + let recurrence_result = recurrence + .after(lower_bound) + .before(upper_bound) + .all(RECURRENCE_LIMIT); for date in recurrence_result.dates { let mut event_instance = event.clone(); - event_instance.start = Some(date.with_timezone(&Local{})); + event_instance.start = Some(date.with_timezone(&Local {})); - if let Some(start) = event.start && let Some(end) = event.end { - let event_duration = end-start; - event_instance.end = Some(event_instance.start.unwrap() + event_duration); + if let Some(start) = event.start + && let Some(end) = event.end + { + let event_duration = end - start; + event_instance.end = + Some(event_instance.start.unwrap() + event_duration); } events.push(event_instance); } - }, + } Err(error) => { - tracing::event!(Level::INFO, "recurrence error occured. Event '{event:?}' is ignored: {error}"); + tracing::event!( + Level::INFO, + "recurrence error occured. Event '{event:?}' is ignored: {error}" + ); } } } } - events.sort_by_key(|event|event.start); + events.sort_by_key(|event| event.start); Ok(CallToolResult::structured(serde_json::json!(events))) } diff --git a/mcp_server_collection/src/lib.rs b/mcp_server_collection/src/lib.rs index 9ae8904..2e41c7a 100644 --- a/mcp_server_collection/src/lib.rs +++ b/mcp_server_collection/src/lib.rs @@ -16,6 +16,8 @@ use axum::Router; use axum::response::Json; use own_assist_common::exit_msg; use serde::{Deserialize, Serialize}; +use tokio::select; +use tokio_util::sync::CancellationToken; use tracing::{Level, event}; #[derive(Debug, Clone, Deserialize, Serialize)] @@ -58,7 +60,7 @@ fn bind_address_format(url: url::Url) -> String { ) } -pub async fn serve(config: Config) { +pub async fn serve(config: Config) -> CancellationToken { let routes = Json( config .servers @@ -84,12 +86,17 @@ pub async fn serve(config: Config) { .inspect_err(exit_msg!("Error bind tcp listener: {e:#?}")) .unwrap(); - let ct = tokio_util::sync::CancellationToken::new(); + let cancellation_token = CancellationToken::new(); + let cloned_cancellation_token = cancellation_token.clone(); let _ = axum::serve(tcp_listener, router) .with_graceful_shutdown(async move { - tokio::signal::ctrl_c().await.unwrap(); - ct.cancel(); + select! { + _ = cloned_cancellation_token.cancelled() => (), + _ = tokio::signal::ctrl_c() => (), + } }) .await; + + cancellation_token } diff --git a/mcp_server_collection/src/main.rs b/mcp_server_collection/src/main.rs index a4cc5da..7fb7101 100644 --- a/mcp_server_collection/src/main.rs +++ b/mcp_server_collection/src/main.rs @@ -1,7 +1,7 @@ use mcp_server_collection::config::Config; use mcp_server_collection::serve; use own_assist_common::{exit_msg, init_tracing_subscriber}; -use tokio::main; +use tokio::{main}; #[main] async fn main() { diff --git a/own_mcp/src/mcp/chat.rs b/own_mcp/src/mcp/chat.rs index 336e374..0740f63 100644 --- a/own_mcp/src/mcp/chat.rs +++ b/own_mcp/src/mcp/chat.rs @@ -3,12 +3,12 @@ use ollama_rs::Ollama; use ollama_rs::error::OllamaError; use ollama_rs::generation::chat::ChatMessage; use ollama_rs::generation::chat::request::ChatMessageRequest; +use ollama_rs::generation::completion::request::GenerationRequest; use ollama_rs::generation::tools::ToolInfo; use rmcp::ServiceError; use rmcp::model::{CallToolRequestParams, CallToolResult}; use serde::Deserialize; use std::collections::HashMap; -use ollama_rs::generation::completion::request::GenerationRequest; use thiserror::Error; #[derive(Debug, Copy, Clone, Default, Deserialize, PartialEq)] @@ -118,7 +118,9 @@ impl AgentChat { let ollama_client_clone = ollama_client.clone(); let model_clone = model.clone(); tokio::spawn(async move { - let _ = ollama_client_clone.generate(GenerationRequest::new(model_clone, "")).await; + let _ = ollama_client_clone + .generate(GenerationRequest::new(model_clone, "")) + .await; }); Ok(Self {