-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathcapabilities_tool.rs
More file actions
99 lines (89 loc) · 3.2 KB
/
capabilities_tool.rs
File metadata and controls
99 lines (89 loc) · 3.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//! Hardware capabilities tool — Phase C: query device for reported GPIO pins.
use super::serial::SerialTransport;
use crate::tools::traits::{Tool, ToolResult};
use async_trait::async_trait;
use serde_json::json;
use std::sync::Arc;
/// Tool: query device capabilities (GPIO pins, LED pin) from firmware.
pub struct HardwareCapabilitiesTool {
/// (board_name, transport) for each serial board.
boards: Vec<(String, Arc<SerialTransport>)>,
}
impl HardwareCapabilitiesTool {
pub(crate) fn new(boards: Vec<(String, Arc<SerialTransport>)>) -> Self {
Self { boards }
}
}
#[async_trait]
impl Tool for HardwareCapabilitiesTool {
fn name(&self) -> &str {
"hardware_capabilities"
}
fn description(&self) -> &str {
"Query connected hardware for reported GPIO pins and LED pin. Use when: user asks what pins are available."
}
fn parameters_schema(&self) -> serde_json::Value {
json!({
"type": "object",
"properties": {
"board": {
"type": "string",
"description": "Optional board name. If omitted, queries all."
}
}
})
}
async fn execute(&self, args: serde_json::Value) -> anyhow::Result<ToolResult> {
let filter = args.get("board").and_then(|v| v.as_str());
let mut outputs = Vec::new();
for (board_name, transport) in &self.boards {
if let Some(b) = filter {
if b != board_name {
continue;
}
}
match transport.capabilities().await {
Ok(result) => {
let output = if result.success {
if let Ok(parsed) =
serde_json::from_str::<serde_json::Value>(&result.output)
{
format!(
"{}: gpio {:?}, led_pin {:?}",
board_name,
parsed.get("gpio").unwrap_or(&json!([])),
parsed.get("led_pin").unwrap_or(&json!(null))
)
} else {
format!("{}: {}", board_name, result.output)
}
} else {
format!(
"{}: {}",
board_name,
result.error.as_deref().unwrap_or("unknown")
)
};
outputs.push(output);
}
Err(e) => {
outputs.push(format!("{}: error - {}", board_name, e));
}
}
}
let output = if outputs.is_empty() {
if filter.is_some() {
"No matching board or capabilities not supported.".to_string()
} else {
"No serial boards configured or capabilities not supported.".to_string()
}
} else {
outputs.join("\n")
};
Ok(ToolResult {
success: !outputs.is_empty(),
output,
error: None,
})
}
}