use std::sync::Arc;
use langchainrust::{A2AServer, LLMChain, OpenAIChat, OpenAIConfig};
use tokio::net::TcpListener;
fn real_llm() -> OpenAIChat {
OpenAIChat::new(OpenAIConfig {
api_key: std::env::var("A2A_API_KEY")
.unwrap_or_else(|_| "sk-6eb65fcf5d17491ca10b984efe1f43e7".to_string()),
base_url: std::env::var("A2A_BASE_URL").unwrap_or_else(|_| {
"https://llm-8xo1b7o30z27y2xc.cn-beijing.maas.aliyuncs.com/compatible-mode/v1"
.to_string()
}), model: std::env::var("A2A_MODEL")
.unwrap_or_else(|_| "qwen3.7-max-2026-06-08".to_string()),
streaming: false,
temperature: Some(0.3),
max_tokens: Some(500),
..Default::default()
})
}
#[tokio::main]
async fn main() {
let host = std::env::var("A2A_HOST").unwrap_or_else(|_| "127.0.0.1".to_string());
let port: u16 = std::env::var("A2A_PORT")
.ok()
.and_then(|v| v.parse().ok())
.unwrap_or(8080);
let template = std::env::var("A2A_QUESTION_TEMPLATE")
.unwrap_or_else(|_| "用一句话回答:{question}".to_string());
let chain = LLMChain::new(real_llm(), template);
let server = A2AServer::new(Arc::new(chain) as Arc<dyn langchainrust::BaseChain>);
let server = match std::env::var("A2A_AUTH_TOKEN").ok() {
Some(token) if !token.is_empty() => server.with_auth_token(&token),
_ => server,
};
let listener = TcpListener::bind((host.as_str(), port))
.await
.unwrap_or_else(|e| {
eprintln!("绑定 {host}:{port} 失败: {e}");
std::process::exit(1);
});
let bound = listener.local_addr().unwrap();
println!("A2A agent 已启动 ✅");
println!(" agent 卡片: http://{bound}/.well-known/agent-card.json");
println!(" 任务入口 : POST http://{bound}/ (tasks/send / tasks/get / tasks/cancel)");
println!(" 技能 : 一句话问答(qwen3.7-max)");
println!("按 Ctrl+C 停止。");
server.serve_on(listener).await.unwrap_or_else(|e| {
eprintln!("A2A 服务异常退出: {e}");
std::process::exit(1);
});
}