1use crate::AiPermission;
2use async_trait::async_trait;
3use origin_domain::Result;
4use serde::{Deserialize, Serialize};
5use std::fmt::Debug;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct ToolDescriptor {
14 pub name: String,
16 pub title: String,
18 pub description: String,
20 pub permission: AiPermission,
22 pub input_schema: serde_json::Value,
24}
25
26impl ToolDescriptor {
27 pub fn new(
28 name: impl Into<String>,
29 title: impl Into<String>,
30 description: impl Into<String>,
31 permission: AiPermission,
32 ) -> Self {
33 Self {
34 name: name.into(),
35 title: title.into(),
36 description: description.into(),
37 permission,
38 input_schema: serde_json::json!({
39 "type": "object",
40 "properties": {},
41 "additionalProperties": false
42 }),
43 }
44 }
45
46 pub fn with_schema(mut self, input_schema: serde_json::Value) -> Self {
47 self.input_schema = input_schema;
48 self
49 }
50}
51
52#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct ToolOutput {
55 pub text: String,
57 pub structured: Option<serde_json::Value>,
59}
60
61impl ToolOutput {
62 pub fn text(text: impl Into<String>) -> Self {
63 Self {
64 text: text.into(),
65 structured: None,
66 }
67 }
68
69 pub fn with_structured(mut self, structured: serde_json::Value) -> Self {
70 self.structured = Some(structured);
71 self
72 }
73}
74
75#[async_trait]
81pub trait Tool: Debug + Send + Sync + 'static {
82 fn descriptor(&self) -> ToolDescriptor;
83
84 async fn call(&self, arguments: serde_json::Value) -> Result<ToolOutput>;
87}