agent_engine/tools/
extension.rs1use std::sync::Arc;
2
3use serde_json::Value;
4
5use crate::extensions::runtime::process::RegisteredExtensionToolSpec;
6use crate::extensions::runtime::ExtensionHandler;
7use crate::{Result, RuntimeError, ToolContext};
8
9pub struct ExtensionTool {
10 runtime_name: String,
11 description: String,
12 input_schema: Value,
13 handler: Arc<dyn ExtensionHandler>,
14 tool_name: String,
15 plugin_id: String,
16}
17
18impl ExtensionTool {
19 pub fn new(
20 plugin_id: &str,
21 spec: RegisteredExtensionToolSpec,
22 handler: Arc<dyn ExtensionHandler>,
23 ) -> Self {
24 Self {
25 runtime_name: format!("{}:{}", plugin_id, spec.name),
26 description: spec.description,
27 input_schema: spec.input_schema,
28 handler,
29 tool_name: spec.name,
30 plugin_id: plugin_id.to_string(),
31 }
32 }
33}
34
35#[async_trait::async_trait]
36impl crate::tools::Tool for ExtensionTool {
37 fn name(&self) -> &str {
38 &self.runtime_name
39 }
40
41 fn description(&self) -> &str {
42 &self.description
43 }
44
45 fn parameters(&self) -> Value {
46 self.input_schema.clone()
47 }
48
49 async fn execute(&self, params: Value, _ctx: ToolContext) -> Result<String> {
50 let value = self
51 .handler
52 .call_tool(&self.tool_name, params)
53 .await
54 .map_err(RuntimeError::Tool)?;
55 if let Some(text) = value.as_str() {
56 Ok(text.to_string())
57 } else if let Some(text) = value.get("content").and_then(Value::as_str) {
58 Ok(text.to_string())
59 } else {
60 Ok(value.to_string())
61 }
62 }
63
64 fn extension_id(&self) -> Option<&str> {
65 Some(&self.plugin_id)
66 }
67}