Refactor tool execution pipeline

This commit is contained in:
2026-06-21 14:30:40 +08:00
parent 3e5f0658b3
commit 99c1e9cd6c
81 changed files with 3587 additions and 5317 deletions
+105
View File
@@ -0,0 +1,105 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "itoa"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "memchr"
version = "2.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
[[package]]
name = "proc-macro2"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
dependencies = [
"proc-macro2",
]
[[package]]
name = "serde"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
]
[[package]]
name = "serde_core"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
dependencies = [
"itoa",
"memchr",
"serde",
"serde_core",
"zmij",
]
[[package]]
name = "syn"
version = "2.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]]
name = "weather"
version = "0.1.0"
dependencies = [
"serde_json",
]
[[package]]
name = "zmij"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
+11
View File
@@ -0,0 +1,11 @@
[package]
name = "weather"
version = "0.1.0"
edition = "2024"
[[bin]]
name = "weather"
path = "src/main.rs"
[dependencies]
serde_json = "1.0"
@@ -0,0 +1,14 @@
name: weather_forecast
desc: 查询指定城市未来7天的每日天气预报(白天/夜间天气、最高/最低温度)。用于"明天天气""这周天气"等问题
type: http
tool: weather
command: forecast
path: /target/release/weather
risk_level: low
timeout_secs: 10
env:
- QWEATHER_KEY
params:
- name: location
required: true
desc: 城市名称,如"北京"、"上海"、"合肥"。支持地级市和县级市
@@ -0,0 +1,14 @@
name: weather_hourly
desc: 查询指定城市未来24小时逐小时天气(温度、天气状况、风力、降水概率)。用于"今晚会下雨吗""下午几点最热"等精确时间天气问题
type: http
tool: weather
command: hourly
path: /target/release/weather
risk_level: low
timeout_secs: 10
env:
- QWEATHER_KEY
params:
- name: location
required: true
desc: 城市名称,如"北京"、"上海"、"合肥"。支持地级市和县级市
+14
View File
@@ -0,0 +1,14 @@
name: weather_now
desc: 查询指定城市的实时天气(温度、体感温度、风向风力、湿度、气压、能见度)。用于回答"今天天气怎么样""北京多少度"等即时天气问题
type: http
tool: weather
command: now
path: /target/release/weather
risk_level: low
timeout_secs: 10
env:
- QWEATHER_KEY
params:
- name: location
required: true
desc: 城市名称,如"北京"、"上海"、"合肥"。支持地级市和县级市
+49
View File
@@ -0,0 +1,49 @@
//! weather — 和风天气
const HOST: &str = "https://devapi.qweather.com/v7";
fn main() {
let input: serde_json::Value = serde_json::from_reader(std::io::stdin()).unwrap();
let mode = std::env::args().nth(2).unwrap_or_else(|| "now".to_string());
let loc = input["params"]["location"].as_str().unwrap_or("北京");
let key = match std::env::var("QWEATHER_KEY") {
Ok(k) if !k.is_empty() => k,
_ => {
println!(r#"{{"type":"result","content":"错误: 缺少环境变量 QWEATHER_KEY(和风天气 API Key),请在 .env 中设置"}}"#);
return;
}
};
if input.get("response").is_none() && input.get("db_response").is_none() {
let (path, desc) = match mode.as_str() {
"now" => ("weather/now", "实时天气"),
"forecast" => ("weather/7d", "7天预报"),
"hourly" => ("weather/24h", "24h逐时"),
_ => { println!(r#"{{"type":"result","content":"未知模式"}}"#); return; }
};
println!("{}", serde_json::json!({
"type":"http","method":"GET",
"url":format!("{HOST}/{path}?location={loc}&key={key}"),
"desc":desc
}));
} else {
let body = &input["response"]["body"];
let ok = body["code"].as_str() == Some("200");
let content = if !ok { "查询失败".into() } else { match mode.as_str() {
"now" => format!("{} {}°C(体感{}°C) {}{}级 湿度{}%",
body["now"]["text"].as_str().unwrap_or("?"), body["now"]["temp"].as_str().unwrap_or("?"),
body["now"]["feelsLike"].as_str().unwrap_or("?"), body["now"]["windDir"].as_str().unwrap_or("?"),
body["now"]["windScale"].as_str().unwrap_or("?"), body["now"]["humidity"].as_str().unwrap_or("?")),
"forecast" => body["daily"].as_array().unwrap_or(&vec![]).iter().take(7)
.map(|d| format!("{}: {}~{}°C", d["fxDate"].as_str().unwrap_or(""),
d["tempMin"].as_str().unwrap_or(""), d["tempMax"].as_str().unwrap_or("")))
.collect::<Vec<_>>().join("\n"),
"hourly" => body["hourly"].as_array().unwrap_or(&vec![]).iter().take(12)
.map(|h| format!("{}: {} {}°C", h["fxTime"].as_str().unwrap_or(""),
h["text"].as_str().unwrap_or(""), h["temp"].as_str().unwrap_or("")))
.collect::<Vec<_>>().join("\n"),
_ => String::new(),
}};
println!("{}", serde_json::json!({"type":"result","content":content}));
}
}