From 88e92a31a3ea8ba13b375f40df8645b70c0a3cc6 Mon Sep 17 00:00:00 2001 From: Logan King Date: Sat, 19 Jul 2025 18:26:47 -0700 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20(assistant=5Fv2):=20add=20speedtest?= =?UTF-8?q?=20feature?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assistant_v2/FEATURE_PROGRESS.md | 2 +- assistant_v2/src/main.rs | 69 ++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/assistant_v2/FEATURE_PROGRESS.md b/assistant_v2/FEATURE_PROGRESS.md index da70e56..c2de9f6 100644 --- a/assistant_v2/FEATURE_PROGRESS.md +++ b/assistant_v2/FEATURE_PROGRESS.md @@ -11,7 +11,7 @@ This document tracks which features from the original assistant have been implem | Display log files | Pending | | Get system info | Done | | List and kill processes | Pending | -| Run internet speed tests | Pending | +| Run internet speed tests | Done | | Set the clipboard contents | Done | | Get the clipboard contents | Done | | Timers with alarm sounds | Pending | diff --git a/assistant_v2/src/main.rs b/assistant_v2/src/main.rs index b5a374c..12faf00 100644 --- a/assistant_v2/src/main.rs +++ b/assistant_v2/src/main.rs @@ -138,6 +138,19 @@ async fn main() -> Result<(), Box> { strict: None, } .into(), + FunctionObject { + name: "speedtest".into(), + description: Some( + "Runs an internet speedtest and returns the results.".into(), + ), + parameters: Some(serde_json::json!({ + "type": "object", + "properties": {}, + "required": [], + })), + strict: None, + } + .into(), FunctionObject { name: "set_screen_brightness".into(), description: Some( @@ -538,6 +551,23 @@ fn get_clipboard_string() -> Result { .map_err(|e| format!("Failed to read clipboard contents: {}", e)) } +fn speedtest() -> Result { + let output = match std::process::Command::new("speedtest-rs").output() { + Ok(output) => String::from_utf8_lossy(&output.stdout).to_string(), + Err(err) => { + if err.kind() == std::io::ErrorKind::NotFound { + return Err( + "speedtest-rs not found. Please install speedtest-rs and add it to your PATH. You can do this by running `cargo install speedtest-rs`".to_string(), + ); + } else { + return Err(format!("Failed to run speedtest-rs: {:?}", err)); + } + } + }; + + Ok(output) +} + async fn handle_requires_action( client: Client, run_object: RunObject, @@ -673,6 +703,17 @@ async fn handle_requires_action( }); } + if tool.function.name == "speedtest" { + let msg = match speedtest() { + Ok(out) => out, + Err(e) => e, + }; + tool_outputs.push(ToolsOutputs { + tool_call_id: Some(tool.id.clone()), + output: Some(msg.into()), + }); + } + if tool.function.name == "set_speech_speed" { let speed = match serde_json::from_str::(&tool.function.arguments) { Ok(v) => v["speed"].as_f64().unwrap_or(1.0) as f32, @@ -840,6 +881,34 @@ mod tests { })); } + #[test] + fn includes_speedtest_function() { + let req = CreateAssistantRequestArgs::default() + .instructions("test") + .model("gpt-4o") + .tools(vec![FunctionObject { + name: "speedtest".into(), + description: Some( + "Runs an internet speedtest and returns the results.".into(), + ), + parameters: Some(serde_json::json!({ + "type": "object", + "properties": {}, + "required": [], + })), + strict: None, + } + .into()]) + .build() + .unwrap(); + + let tools = req.tools.unwrap(); + assert!(tools.iter().any(|t| match t { + async_openai::types::AssistantTools::Function(f) => f.function.name == "speedtest", + _ => false, + })); + } + #[test] fn includes_set_screen_brightness_function() { let req = CreateAssistantRequestArgs::default()