update dependencies

This commit is contained in:
2026-07-19 11:16:10 +02:00
parent 78ba2b7b3d
commit 06ef1ba2dd
11 changed files with 478 additions and 654 deletions
Generated
+399 -601
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -1,2 +1,3 @@
[workspace] [workspace]
members = ["cli", "common", "mcp_server_collection", "own_mcp"] members = ["cli", "common", "mcp_server_collection", "own_mcp"]
resolver = "3"
+2 -2
View File
@@ -7,7 +7,7 @@ license = "GPL-3.0"
[dependencies] [dependencies]
ollama-rs = { version = "0.3.4", features = ["macros", "headers"] } ollama-rs = { version = "0.3.4", features = ["macros", "headers"] }
tokio = { version = "1.50.0", features = ["rt", "rt-multi-thread", "macros", "io-std"] } tokio = { version = "1.50.0", features = ["rt", "rt-multi-thread", "macros", "io-std"] }
rmcp = { version = "1.3.0", features = ["client"] } rmcp = { version = "2.2.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"
@@ -20,7 +20,7 @@ indicatif = "0.18.4"
console = "0.16.3" console = "0.16.3"
clap = { version = "4.6.0", features = ["derive"] } clap = { version = "4.6.0", features = ["derive"] }
base64 = "0.22.1" base64 = "0.22.1"
cpal = "0.17.3" cpal = "0.18.1"
rodio = "0.22.2" rodio = "0.22.2"
tokio-util = { version = "0.7.18", optional = true } tokio-util = { version = "0.7.18", optional = true }
+11 -8
View File
@@ -10,11 +10,11 @@ use crate::model::create_model_from_config;
use base64::Engine; use base64::Engine;
use clap::Parser; use clap::Parser;
use cpal::traits::HostTrait; use cpal::traits::HostTrait;
use mcp_server_collection::McpServerError;
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; use tokio_util::sync::CancellationToken;
use mcp_server_collection::McpServerError;
/// partial mcp client with cli and voice interaction /// partial mcp client with cli and voice interaction
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
@@ -68,7 +68,9 @@ 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")]
async fn launch_mcp_server(config: mcp_server_collection::config::Config) -> Result<(CancellationToken, JoinHandle<std::io::Result<()>>), McpServerError> { async fn launch_mcp_server(
config: mcp_server_collection::config::Config,
) -> Result<(CancellationToken, JoinHandle<std::io::Result<()>>), McpServerError> {
let handle = mcp_server_collection::serve_in_background(config).await?; let handle = mcp_server_collection::serve_in_background(config).await?;
Ok(handle) Ok(handle)
@@ -85,13 +87,14 @@ async fn main() {
init_tracing_subscriber(); init_tracing_subscriber();
#[cfg(feature = "built-in-mcp-collection")] #[cfg(feature = "built-in-mcp-collection")]
let mcp_config = mcp_server_collection::config::Config::from_file().inspect_err(exit_msg!("error loading server.toml")) let mcp_config = mcp_server_collection::config::Config::from_file()
.unwrap(); .inspect_err(exit_msg!("error loading server.toml"))
.unwrap();
#[cfg(feature = "built-in-mcp-collection")] #[cfg(feature = "built-in-mcp-collection")]
let (mcp_server_ct, mcp_server_task) = launch_mcp_server(mcp_config).await let (mcp_server_ct, mcp_server_task) = launch_mcp_server(mcp_config)
.inspect_err(exit_msg!("error launching mcp server")) .await
.unwrap(); .inspect_err(exit_msg!("error launching mcp server"))
.unwrap();
let config = Config::from_file() let config = Config::from_file()
.inspect_err(exit_msg!("error loading assist.toml")) .inspect_err(exit_msg!("error loading assist.toml"))
+2 -2
View File
@@ -5,7 +5,7 @@ edition = "2024"
license = "GPL-3.0" license = "GPL-3.0"
[dependencies] [dependencies]
rmcp = { version = "1.7.0", features = ["server", "transport-streamable-http-server-session", "transport-streamable-http-server"] } rmcp = { version = "2.2.0", features = ["server", "transport-streamable-http-server-session", "transport-streamable-http-server"] }
chrono = "0.4.44" chrono = "0.4.44"
axum = "0.8.9" axum = "0.8.9"
serde = { version = "1.0.228", features = ["derive"] } serde = { version = "1.0.228", features = ["derive"] }
@@ -15,7 +15,7 @@ tokio-util = "0.7.18"
tracing = "0.1.44" tracing = "0.1.44"
url = { version = "2.5.8", features = ["serde"] } url = { version = "2.5.8", features = ["serde"] }
uuid = { version = "1.23.1", features = ["v4"], optional = true } uuid = { version = "1.23.1", features = ["v4"], optional = true }
tower-http = { version = "0.6.11", features = ["auth"], optional = true } tower-http = { version = "0.7.0", features = ["auth"], optional = true }
thiserror = { version = "2.0.18", optional = true } thiserror = { version = "2.0.18", optional = true }
libdav = { version = "0.10.5", optional = true } libdav = { version = "0.10.5", optional = true }
icalendar = { version = "0.17.10", optional = true, features = ["chrono-tz", "recurrence"] } icalendar = { version = "0.17.10", optional = true, features = ["chrono-tz", "recurrence"] }
+9 -2
View File
@@ -23,8 +23,15 @@ pub(crate) fn get_caldav_client(
username: &str, username: &str,
password: &str, password: &str,
) -> AuthorizedCaldavClient { ) -> AuthorizedCaldavClient {
let https_connector: HttpsConnector<HttpConnector> = HttpsConnectorBuilder::new() let https_connector = HttpsConnectorBuilder::new()
.with_webpki_roots() .with_native_roots()
.unwrap_or_else(|_| {
event!(
Level::WARN,
"unable to use native root certificates. Using webpki instead"
);
HttpsConnectorBuilder::new().with_webpki_roots()
})
.https_only() .https_only()
.enable_http1() .enable_http1()
.build(); .build();
+14 -10
View File
@@ -69,7 +69,9 @@ pub enum McpServerError {
IoError(#[from] std::io::Error), IoError(#[from] std::io::Error),
} }
pub async fn serve_in_background(config: Config) -> Result<(CancellationToken, JoinHandle<std::io::Result<()>>), McpServerError> { pub async fn serve_in_background(
config: Config,
) -> Result<(CancellationToken, JoinHandle<std::io::Result<()>>), McpServerError> {
let routes = Json( let routes = Json(
config config
.servers .servers
@@ -88,19 +90,21 @@ pub async fn serve_in_background(config: Config) -> Result<(CancellationToken, J
.unwrap_or(url::Url::parse("http://localhost:8000").unwrap()); .unwrap_or(url::Url::parse("http://localhost:8000").unwrap());
event!(Level::INFO, "binding address at {bind_address}"); event!(Level::INFO, "binding address at {bind_address}");
let tcp_listener = tokio::net::TcpListener::bind(bind_address_format(bind_address)) let tcp_listener = tokio::net::TcpListener::bind(bind_address_format(bind_address)).await?;
.await?;
let cancellation_token = CancellationToken::new(); let cancellation_token = CancellationToken::new();
let cloned_cancellation_token = cancellation_token.clone(); let cloned_cancellation_token = cancellation_token.clone();
let handle = tokio::task::spawn(axum::serve(tcp_listener, router) let handle = tokio::task::spawn(
.with_graceful_shutdown(async move { axum::serve(tcp_listener, router)
select! { .with_graceful_shutdown(async move {
_ = cloned_cancellation_token.cancelled() => (), select! {
_ = tokio::signal::ctrl_c() => (), _ = cloned_cancellation_token.cancelled() => (),
} _ = tokio::signal::ctrl_c() => (),
}).into_future()); }
})
.into_future(),
);
Ok((cancellation_token, handle)) Ok((cancellation_token, handle))
} }
+13 -6
View File
@@ -1,7 +1,7 @@
use mcp_server_collection::config::Config; use mcp_server_collection::config::Config;
use mcp_server_collection::{serve_in_background, McpServerError}; use mcp_server_collection::{McpServerError, serve_in_background};
use own_assist_common::{exit_msg, exit_with_error_message, init_tracing_subscriber}; use own_assist_common::{exit_msg, exit_with_error_message, init_tracing_subscriber};
use tokio::{main}; use tokio::main;
#[main] #[main]
async fn main() { async fn main() {
@@ -11,10 +11,17 @@ async fn main() {
.inspect_err(exit_msg!("Error loading config")) .inspect_err(exit_msg!("Error loading config"))
.unwrap(); .unwrap();
let (_, join_handle) = serve_in_background(config).await.inspect_err(|err| match err { let (_, join_handle) = serve_in_background(config)
McpServerError::McpServerHandlerError(error) => exit_with_error_message(error, "Error handling server"), .await
McpServerError::IoError(error) => exit_with_error_message(error, "Error binding tcp listener") .inspect_err(|err| match err {
}).unwrap(); McpServerError::McpServerHandlerError(error) => {
exit_with_error_message(error, "Error handling server")
}
McpServerError::IoError(error) => {
exit_with_error_message(error, "Error binding tcp listener")
}
})
.unwrap();
join_handle.await.unwrap().unwrap(); join_handle.await.unwrap().unwrap();
} }
+2 -2
View File
@@ -8,13 +8,13 @@ license = "GPL-3.0"
ollama-rs = {version = "0.3.4", features = ["macros", "headers"]} ollama-rs = {version = "0.3.4", features = ["macros", "headers"]}
reqwest = { version = "0.13.2", features = ["stream", "multipart", "form"] } reqwest = { version = "0.13.2", features = ["stream", "multipart", "form"] }
tokio = { version = "1.50.0", features = ["rt", "rt-multi-thread", "macros"] } tokio = { version = "1.50.0", features = ["rt", "rt-multi-thread", "macros"] }
rmcp = {version="1.3.0", features = ["transport-streamable-http-client-reqwest", "reqwest", "client", "auth", "transport-child-process"]} rmcp = {version="2.2.0", features = ["transport-streamable-http-client-reqwest", "reqwest", "client", "auth", "transport-child-process"]}
log = {version = "0.4.29"} log = {version = "0.4.29"}
env_logger = "0.11.10" env_logger = "0.11.10"
serde = { version = "1.0.228", features = ["derive"] } serde = { version = "1.0.228", features = ["derive"] }
thiserror = "2.0.17" thiserror = "2.0.17"
url = "2.5.8" url = "2.5.8"
rand = "0.10.0" rand = "0.10.0"
cpal = "0.17.3" cpal = "0.18.1"
hound = "3.5.1" hound = "3.5.1"
bytes = "1.11.1" bytes = "1.11.1"
+11 -13
View File
@@ -1,5 +1,5 @@
use cpal::traits::{DeviceTrait, StreamTrait}; use cpal::traits::{DeviceTrait, StreamTrait};
use cpal::{BuildStreamError, Device, SampleFormat, SizedSample, Stream, SupportedStreamConfig}; use cpal::{Device, Error, SampleFormat, SizedSample, Stream, SupportedStreamConfig};
use hound::WavSpec; use hound::WavSpec;
use log::{debug, error, info, trace}; use log::{debug, error, info, trace};
use std::fmt::Debug; use std::fmt::Debug;
@@ -38,9 +38,9 @@ fn build_stream<T: SizedSample + Debug + hound::Sample + Send + Into<f64>>(
device_config: SupportedStreamConfig, device_config: SupportedStreamConfig,
samples: SampleArc, samples: SampleArc,
sample_format: SampleFormat, sample_format: SampleFormat,
) -> Result<Stream, BuildStreamError> { ) -> Result<Stream, Error> {
mic.build_input_stream( mic.build_input_stream(
&device_config.into(), device_config.into(),
move |input: &[T], _info| stream_callback::<T>(input, samples.clone(), sample_format), move |input: &[T], _info| stream_callback::<T>(input, samples.clone(), sample_format),
|e| { |e| {
error!("a stream error occurred while trying to record: {:?}", e); error!("a stream error occurred while trying to record: {:?}", e);
@@ -70,9 +70,7 @@ pub enum RecordingError {
#[error("unsupported sample format")] #[error("unsupported sample format")]
UnsupportedSampleFormat(SampleFormat), UnsupportedSampleFormat(SampleFormat),
#[error(transparent)] #[error(transparent)]
PlayStreamError(#[from] cpal::PlayStreamError), StreamError(#[from] cpal::Error),
#[error(transparent)]
BuildStreamError(#[from] BuildStreamError),
#[error("thread poisoned")] #[error("thread poisoned")]
ThreadPoison, ThreadPoison,
#[error("recording was already stopped")] #[error("recording was already stopped")]
@@ -81,23 +79,23 @@ pub enum RecordingError {
fn start_recording_blocking_with_parameters( fn start_recording_blocking_with_parameters(
mic: &Device, mic: &Device,
device_config: &SupportedStreamConfig, device_config: SupportedStreamConfig,
sample_format: SampleFormat, sample_format: SampleFormat,
samples: SampleArc, samples: SampleArc,
should_stop: Arc<Mutex<bool>>, should_stop: Arc<Mutex<bool>>,
) -> Result<(), RecordingError> { ) -> Result<(), RecordingError> {
let stream = match sample_format { let stream = match sample_format {
SampleFormat::I8 => { SampleFormat::I8 => {
build_stream::<i8>(mic, device_config.clone(), samples.clone(), sample_format)? build_stream::<i8>(mic, device_config, samples.clone(), sample_format)?
} }
SampleFormat::I16 => { SampleFormat::I16 => {
build_stream::<i16>(mic, device_config.clone(), samples.clone(), sample_format)? build_stream::<i16>(mic, device_config, samples.clone(), sample_format)?
} }
SampleFormat::I32 => { SampleFormat::I32 => {
build_stream::<i32>(mic, device_config.clone(), samples.clone(), sample_format)? build_stream::<i32>(mic, device_config, samples.clone(), sample_format)?
} }
SampleFormat::F32 => { SampleFormat::F32 => {
build_stream::<f32>(mic, device_config.clone(), samples.clone(), sample_format)? build_stream::<f32>(mic, device_config, samples.clone(), sample_format)?
} }
sample_format => { sample_format => {
return Err(RecordingError::UnsupportedSampleFormat(sample_format)); return Err(RecordingError::UnsupportedSampleFormat(sample_format));
@@ -135,11 +133,11 @@ pub fn start(
let thread_samples = samples.clone(); let thread_samples = samples.clone();
let thread_recording_stop = recording_should_stop.clone(); let thread_recording_stop = recording_should_stop.clone();
let thread_device_config = device_config.clone(); let thread_device_config = device_config;
let record_thread_handle = thread::spawn(move || { let record_thread_handle = thread::spawn(move || {
start_recording_blocking_with_parameters( start_recording_blocking_with_parameters(
&microphone, &microphone,
&thread_device_config, thread_device_config,
sample_format, sample_format,
thread_samples, thread_samples,
thread_recording_stop, thread_recording_stop,
+12 -6
View File
@@ -1,6 +1,6 @@
use crate::mcp::MCPClient; use crate::mcp::MCPClient;
use ollama_rs::Ollama; 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::completion::request::GenerationRequest;
@@ -102,13 +102,13 @@ pub enum ChatError {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum RestrictedToolCallResult { pub enum RestrictedToolCallResult {
Granted(CallToolResult), Granted(CallToolResult),
Denied Denied,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ToolUsage { pub struct ToolUsage {
pub call: ToolCall, pub call: ToolCall,
pub result: RestrictedToolCallResult pub result: RestrictedToolCallResult,
} }
impl AgentChat { impl AgentChat {
@@ -255,10 +255,14 @@ impl AgentChat {
.call_tool(tool_call, &mut permission_request_callback) .call_tool(tool_call, &mut permission_request_callback)
.await?; .await?;
tool_usages.push(ToolUsage{call: tool_call.clone(), result: restricted_result.clone()}); tool_usages.push(ToolUsage {
call: tool_call.clone(),
result: restricted_result.clone(),
});
// serialize structured content if it exists // serialize structured content if it exists
if let RestrictedToolCallResult::Granted(result) = restricted_result.clone() && let Some(structured_content) = result.structured_content if let RestrictedToolCallResult::Granted(result) = restricted_result.clone()
&& let Some(structured_content) = result.structured_content
{ {
log::debug!("structured content: {structured_content:#?}"); log::debug!("structured content: {structured_content:#?}");
@@ -272,7 +276,9 @@ impl AgentChat {
.filter_map(|content| content.as_text()) .filter_map(|content| content.as_text())
.map(|text_content| text_content.text.clone()) .map(|text_content| text_content.text.clone())
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
RestrictedToolCallResult::Denied => vec![String::from("Tool Permission Denied by the user")], RestrictedToolCallResult::Denied => {
vec![String::from("Tool Permission Denied by the user")]
}
}; };
log::debug!("contents: {contents:#?}"); log::debug!("contents: {contents:#?}");