update formatting
restructure project add cancellation token to cancel mcp server collection from serving
This commit is contained in:
+1
-1
@@ -3,5 +3,5 @@
|
|||||||
assist.toml
|
assist.toml
|
||||||
server.toml
|
server.toml
|
||||||
temporary_audio
|
temporary_audio
|
||||||
src/human_interface/.AUTH_HEADER
|
cli/src/human_interface/.AUTH_HEADER
|
||||||
.idea
|
.idea
|
||||||
|
|||||||
Generated
+2
-1
@@ -1921,7 +1921,7 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "own_assist"
|
name = "own_assist_cli"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
@@ -1940,6 +1940,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"thiserror 2.0.18",
|
"thiserror 2.0.18",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "own_assist"
|
name = "own_assist_cli"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
@@ -10,9 +10,9 @@ rmcp = { version = "1.3.0", features = ["client"] }
|
|||||||
log = { version = "0.4.29" }
|
log = { version = "0.4.29" }
|
||||||
serde = { version = "1.0.228", features = ["derive"] }
|
serde = { version = "1.0.228", features = ["derive"] }
|
||||||
url = "2.5.8"
|
url = "2.5.8"
|
||||||
own_mcp = { path = "own_mcp" }
|
own_mcp = { path = "../own_mcp" }
|
||||||
own_assist_common = { path = "common" }
|
own_assist_common = { path = "../common" }
|
||||||
mcp_server_collection = { path = "mcp_server_collection", optional = true}
|
mcp_server_collection = { path = "../mcp_server_collection", optional = true}
|
||||||
thiserror = "2.0.18"
|
thiserror = "2.0.18"
|
||||||
dialoguer = "0.12.0"
|
dialoguer = "0.12.0"
|
||||||
indicatif = "0.18.4"
|
indicatif = "0.18.4"
|
||||||
@@ -21,7 +21,8 @@ clap = { version = "4.6.0", features = ["derive"] }
|
|||||||
base64 = "0.22.1"
|
base64 = "0.22.1"
|
||||||
cpal = "0.17.3"
|
cpal = "0.17.3"
|
||||||
rodio = "0.22.2"
|
rodio = "0.22.2"
|
||||||
|
tokio-util = { version = "0.7.18", optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["built-in-mcp-collection"]
|
default = ["built-in-mcp-collection"]
|
||||||
built-in-mcp-collection = ["dep:mcp_server_collection"]
|
built-in-mcp-collection = ["dep:mcp_server_collection", "dep:tokio-util"]
|
||||||
@@ -14,6 +14,7 @@ use own_assist_common::config_loader::ConfigLoadingError;
|
|||||||
use own_assist_common::{exit_msg, init_tracing_subscriber};
|
use own_assist_common::{exit_msg, init_tracing_subscriber};
|
||||||
use own_mcp::AgentChat;
|
use own_mcp::AgentChat;
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
|
use tokio_util::sync::CancellationToken;
|
||||||
|
|
||||||
/// partial mcp client with cli and voice interaction
|
/// partial mcp client with cli and voice interaction
|
||||||
#[derive(Parser, Debug)]
|
#[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")]
|
#[cfg(feature = "built-in-mcp-collection")]
|
||||||
fn launch_mcp_server() -> Result<JoinHandle<()>, ConfigLoadingError> {
|
fn launch_mcp_server() -> Result<JoinHandle<CancellationToken>, ConfigLoadingError> {
|
||||||
let config = mcp_server_collection::config::Config::from_file()?;
|
let config = mcp_server_collection::config::Config::from_file()?;
|
||||||
|
|
||||||
let handle = tokio::task::spawn(mcp_server_collection::serve(config));
|
let handle = tokio::task::spawn(mcp_server_collection::serve(config));
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
use tracing::Level;
|
|
||||||
use chrono::{Duration, Local};
|
|
||||||
use crate::caldav::client::{
|
use crate::caldav::client::{
|
||||||
AuthorizedCaldavClient, find_calendars, get_caldav_client, get_components, upload_components,
|
AuthorizedCaldavClient, find_calendars, get_caldav_client, get_components, upload_components,
|
||||||
};
|
};
|
||||||
|
use crate::caldav::event::McpEvent;
|
||||||
use crate::caldav::todo::McpTodo;
|
use crate::caldav::todo::McpTodo;
|
||||||
use crate::server_handler::{
|
use crate::server_handler::{
|
||||||
McpServerHandler, McpServerHandlerError, get_additional_property, get_property_as_string,
|
McpServerHandler, McpServerHandlerError, get_additional_property, get_property_as_string,
|
||||||
};
|
};
|
||||||
|
use chrono::{Duration, Local};
|
||||||
use http::Uri;
|
use http::Uri;
|
||||||
use icalendar::{Event, EventLike, Todo};
|
use icalendar::{Event, EventLike, Todo};
|
||||||
use libdav::dav::FoundCollection;
|
use libdav::dav::FoundCollection;
|
||||||
@@ -19,7 +19,7 @@ use serde::Deserialize;
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use toml::Value;
|
use toml::Value;
|
||||||
use toml::map::Map;
|
use toml::map::Map;
|
||||||
use crate::caldav::event::McpEvent;
|
use tracing::Level;
|
||||||
|
|
||||||
mod client;
|
mod client;
|
||||||
mod datetime_conversion;
|
mod datetime_conversion;
|
||||||
@@ -193,8 +193,11 @@ impl CalDavHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tool(description = "gets events of next 7 days")]
|
#[tool(description = "gets events of next 7 days")]
|
||||||
async fn get_upcoming_events(&self, parameters: Parameters<GetCalendarComponentParameters>) -> Result<CallToolResult, ErrorData> {
|
async fn get_upcoming_events(
|
||||||
const DAYS_DELTA: Duration = Duration::days(7);
|
&self,
|
||||||
|
parameters: Parameters<GetCalendarComponentParameters>,
|
||||||
|
) -> Result<CallToolResult, ErrorData> {
|
||||||
|
const DAYS_DELTA: Duration = Duration::days(7);
|
||||||
const RECURRENCE_LIMIT: u16 = 10;
|
const RECURRENCE_LIMIT: u16 = 10;
|
||||||
|
|
||||||
let calendar = self.get_calendar_by_name(parameters.0.calendar_name)?;
|
let calendar = self.get_calendar_by_name(parameters.0.calendar_name)?;
|
||||||
@@ -203,7 +206,7 @@ impl CalDavHandler {
|
|||||||
let mut events: Vec<McpEvent> = Vec::new();
|
let mut events: Vec<McpEvent> = Vec::new();
|
||||||
|
|
||||||
for component in components {
|
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 event: McpEvent = event_component.clone().try_into()?;
|
||||||
|
|
||||||
let lower_bound = Local::now().with_timezone(&icalendar::Tz::Local(Local));
|
let lower_bound = Local::now().with_timezone(&icalendar::Tz::Local(Local));
|
||||||
@@ -212,28 +215,37 @@ impl CalDavHandler {
|
|||||||
|
|
||||||
match recurrence {
|
match recurrence {
|
||||||
Ok(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 {
|
for date in recurrence_result.dates {
|
||||||
let mut event_instance = event.clone();
|
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 {
|
if let Some(start) = event.start
|
||||||
let event_duration = end-start;
|
&& let Some(end) = event.end
|
||||||
event_instance.end = Some(event_instance.start.unwrap() + event_duration);
|
{
|
||||||
|
let event_duration = end - start;
|
||||||
|
event_instance.end =
|
||||||
|
Some(event_instance.start.unwrap() + event_duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
events.push(event_instance);
|
events.push(event_instance);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Err(error) => {
|
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)))
|
Ok(CallToolResult::structured(serde_json::json!(events)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ use axum::Router;
|
|||||||
use axum::response::Json;
|
use axum::response::Json;
|
||||||
use own_assist_common::exit_msg;
|
use own_assist_common::exit_msg;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use tokio::select;
|
||||||
|
use tokio_util::sync::CancellationToken;
|
||||||
use tracing::{Level, event};
|
use tracing::{Level, event};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
#[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(
|
let routes = Json(
|
||||||
config
|
config
|
||||||
.servers
|
.servers
|
||||||
@@ -84,12 +86,17 @@ pub async fn serve(config: Config) {
|
|||||||
.inspect_err(exit_msg!("Error bind tcp listener: {e:#?}"))
|
.inspect_err(exit_msg!("Error bind tcp listener: {e:#?}"))
|
||||||
.unwrap();
|
.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)
|
let _ = axum::serve(tcp_listener, router)
|
||||||
.with_graceful_shutdown(async move {
|
.with_graceful_shutdown(async move {
|
||||||
tokio::signal::ctrl_c().await.unwrap();
|
select! {
|
||||||
ct.cancel();
|
_ = cloned_cancellation_token.cancelled() => (),
|
||||||
|
_ = tokio::signal::ctrl_c() => (),
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
cancellation_token
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use mcp_server_collection::config::Config;
|
use mcp_server_collection::config::Config;
|
||||||
use mcp_server_collection::serve;
|
use mcp_server_collection::serve;
|
||||||
use own_assist_common::{exit_msg, init_tracing_subscriber};
|
use own_assist_common::{exit_msg, init_tracing_subscriber};
|
||||||
use tokio::main;
|
use tokio::{main};
|
||||||
|
|
||||||
#[main]
|
#[main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ use ollama_rs::Ollama;
|
|||||||
use ollama_rs::error::OllamaError;
|
use ollama_rs::error::OllamaError;
|
||||||
use ollama_rs::generation::chat::ChatMessage;
|
use ollama_rs::generation::chat::ChatMessage;
|
||||||
use ollama_rs::generation::chat::request::ChatMessageRequest;
|
use ollama_rs::generation::chat::request::ChatMessageRequest;
|
||||||
|
use ollama_rs::generation::completion::request::GenerationRequest;
|
||||||
use ollama_rs::generation::tools::ToolInfo;
|
use ollama_rs::generation::tools::ToolInfo;
|
||||||
use rmcp::ServiceError;
|
use rmcp::ServiceError;
|
||||||
use rmcp::model::{CallToolRequestParams, CallToolResult};
|
use rmcp::model::{CallToolRequestParams, CallToolResult};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use ollama_rs::generation::completion::request::GenerationRequest;
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Default, Deserialize, PartialEq)]
|
#[derive(Debug, Copy, Clone, Default, Deserialize, PartialEq)]
|
||||||
@@ -118,7 +118,9 @@ impl AgentChat {
|
|||||||
let ollama_client_clone = ollama_client.clone();
|
let ollama_client_clone = ollama_client.clone();
|
||||||
let model_clone = model.clone();
|
let model_clone = model.clone();
|
||||||
tokio::spawn(async move {
|
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 {
|
Ok(Self {
|
||||||
|
|||||||
Reference in New Issue
Block a user