Add /connect command to REPL for provider health check

New REPL command:
  /connect - Check connectivity to all configured providers

Features:
- Lists all providers with health status (✓/✗)
- Shows healthy/unhealthy status for each
- Summarizes overall health

Updated:
- Repl struct now holds provider_registry reference
- handle_command() is now async to support health checks
- Help text updated with new command

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
2026-03-19 15:17:47 +01:00
parent b52d82dec5
commit 9f1b5f908d
2 changed files with 48 additions and 8 deletions

View File

@@ -1,21 +1,26 @@
use crate::agents::{AgentRequest, AgentTrait}; use crate::agents::{AgentRequest, AgentTrait};
use crate::providers::TaskType; use crate::providers::{ProviderRegistry, TaskType};
use std::io::{self, Write}; use std::io::{self, Write};
use std::sync::Arc;
/// Interactive REPL for svibe /// Interactive REPL for svibe
pub struct Repl { pub struct Repl {
agent: std::sync::Arc<dyn AgentTrait>, agent: Arc<dyn AgentTrait>,
provider_registry: Arc<ProviderRegistry>,
} }
impl Repl { impl Repl {
pub fn new(agent: std::sync::Arc<dyn AgentTrait>) -> Self { pub fn new(agent: Arc<dyn AgentTrait>, provider_registry: Arc<ProviderRegistry>) -> Self {
Self { agent } Self {
agent,
provider_registry,
}
} }
/// Run the REPL (async version) /// Run the REPL (async version)
pub async fn run(&self) -> Result<(), Box<dyn std::error::Error>> { pub async fn run(&self) -> Result<(), Box<dyn std::error::Error>> {
println!("svibe REPL - Type 'exit' or 'quit' to leave"); println!("svibe REPL - Type 'exit' or 'quit' to leave");
println!("Commands: /help, /clear, /status, /agents, /tools"); println!("Commands: /help, /clear, /status, /agents, /tools, /connect");
println!(); println!();
let stdin = io::stdin(); let stdin = io::stdin();
@@ -44,7 +49,7 @@ impl Repl {
} }
if input.starts_with('/') { if input.starts_with('/') {
self.handle_command(input)?; self.handle_command(input).await?;
continue; continue;
} }
@@ -79,7 +84,7 @@ impl Repl {
self.agent.process(request).await self.agent.process(request).await
} }
fn handle_command(&self, input: &str) -> Result<(), Box<dyn std::error::Error>> { async fn handle_command(&self, input: &str) -> Result<(), Box<dyn std::error::Error>> {
let parts: Vec<&str> = input.split_whitespace().collect(); let parts: Vec<&str> = input.split_whitespace().collect();
match parts.get(0).copied() { match parts.get(0).copied() {
@@ -92,6 +97,7 @@ Available commands:
/status Show agent status and metrics /status Show agent status and metrics
/agents List available agents /agents List available agents
/tools List available tools /tools List available tools
/connect Check connectivity to all providers
/exit, /quit, :q Exit the REPL /exit, /quit, :q Exit the REPL
Just type your task to get started! Just type your task to get started!
@@ -126,6 +132,9 @@ Metrics:
Some("tools") | Some("/tools") => { Some("tools") | Some("/tools") => {
println!("Tool listing not available in this context"); println!("Tool listing not available in this context");
} }
Some("connect") | Some("/connect") => {
self.check_connectivity().await?;
}
_ => { _ => {
println!("Unknown command. Type /help for available commands."); println!("Unknown command. Type /help for available commands.");
} }
@@ -133,4 +142,35 @@ Metrics:
Ok(()) Ok(())
} }
async fn check_connectivity(&self) -> Result<(), Box<dyn std::error::Error>> {
println!("\nChecking provider connectivity...\n");
let health = self.provider_registry.health_check_all().await;
let providers = self.provider_registry.list();
if providers.is_empty() {
println!("No providers configured.");
return Ok(());
}
let mut all_healthy = true;
for provider in providers {
let healthy = health.get(provider).copied().unwrap_or(false);
let status = if healthy { "✓" } else { "✗" };
println!(" {} {}: {}", provider, status, if healthy { "healthy" } else { "unhealthy" });
if !healthy {
all_healthy = false;
}
}
println!();
if all_healthy {
println!("All providers are healthy!");
} else {
println!("Some providers are unhealthy. Check your configuration.");
}
Ok(())
}
} }

View File

@@ -74,7 +74,7 @@ async fn main() -> anyhow::Result<()> {
match cli.command { match cli.command {
None | Some(Commands::Repl) => { None | Some(Commands::Repl) => {
// Start REPL // Start REPL
let repl = Repl::new(agent); let repl = Repl::new(agent, provider_registry.clone());
if let Err(e) = repl.run().await { if let Err(e) = repl.run().await {
eprintln!("REPL error: {}", e); eprintln!("REPL error: {}", e);
} }