1use std::collections::BTreeMap;
2use std::convert::Infallible;
3
4use tonic::codegen::async_trait;
5
6use crate::catalog::Catalog;
7use crate::error::{Error, Result};
8
9#[derive(Clone, Debug, Default, Eq, PartialEq)]
10pub struct Subject {
12 pub id: String,
14 pub kind: String,
16 pub display_name: String,
18 pub auth_source: String,
20}
21
22#[derive(Clone, Debug, Default, Eq, PartialEq)]
23pub struct Credential {
25 pub mode: String,
27 pub subject_id: String,
29 pub connection: String,
31 pub instance: String,
33}
34
35#[derive(Clone, Debug, Default, Eq, PartialEq)]
36pub struct Access {
38 pub policy: String,
40 pub role: String,
42}
43
44#[derive(Clone, Debug, Default, Eq, PartialEq)]
45pub struct Host {
47 pub public_base_url: String,
49}
50
51#[derive(Clone, Debug, Default, PartialEq)]
52pub struct Request {
54 pub token: String,
56 pub connection_params: BTreeMap<String, String>,
58 pub subject: Subject,
60 pub credential: Credential,
62 pub access: Access,
64 pub host: Host,
66 pub idempotency_key: String,
68 pub workflow: serde_json::Map<String, serde_json::Value>,
72 pub invocation_token: String,
74}
75
76impl Request {
77 pub fn connection_param(&self, name: &str) -> Option<&str> {
79 self.connection_params.get(name).map(String::as_str)
80 }
81
82 pub fn invocation_token(&self) -> &str {
84 &self.invocation_token
85 }
86
87 pub async fn invoker(
89 &self,
90 ) -> std::result::Result<crate::PluginInvoker, crate::PluginInvokerError> {
91 crate::PluginInvoker::connect(self.invocation_token()).await
92 }
93
94 pub async fn workflow_manager(
96 &self,
97 ) -> std::result::Result<crate::WorkflowManager, crate::WorkflowManagerError> {
98 crate::WorkflowManager::connect_with_idempotency_key(
99 self.invocation_token(),
100 self.idempotency_key.trim(),
101 )
102 .await
103 }
104
105 pub async fn agent_manager(
107 &self,
108 ) -> std::result::Result<crate::AgentManager, crate::AgentManagerError> {
109 crate::AgentManager::connect(self.invocation_token()).await
110 }
111}
112
113#[derive(Clone, Debug, Eq, PartialEq)]
114pub struct Response<T> {
116 pub status: Option<u16>,
118 pub body: T,
120}
121
122impl<T> Response<T> {
123 pub fn new(status: u16, body: T) -> Self {
125 Self {
126 status: Some(status),
127 body,
128 }
129 }
130}
131
132pub fn ok<T>(body: T) -> Response<T> {
134 Response::new(200, body)
135}
136
137pub trait IntoResponse<T> {
139 fn into_response(self) -> Response<T>;
141}
142
143impl<T> IntoResponse<T> for Response<T> {
144 fn into_response(self) -> Response<T> {
145 self
146 }
147}
148
149impl<T> IntoResponse<T> for T {
150 fn into_response(self) -> Response<T> {
151 ok(self)
152 }
153}
154
155#[derive(Clone, Debug, Default, Eq, PartialEq)]
156pub struct RuntimeMetadata {
158 pub name: String,
160 pub display_name: String,
162 pub description: String,
164 pub version: String,
166}
167
168#[async_trait]
169pub trait Provider: Send + Sync + 'static {
171 async fn configure(
173 &self,
174 _name: &str,
175 _config: serde_json::Map<String, serde_json::Value>,
176 ) -> Result<()> {
177 Ok(())
178 }
179
180 fn metadata(&self) -> Option<RuntimeMetadata> {
182 None
183 }
184
185 fn warnings(&self) -> Vec<String> {
187 Vec::new()
188 }
189
190 async fn health_check(&self) -> Result<()> {
192 Ok(())
193 }
194
195 async fn start(&self) -> Result<()> {
197 Ok(())
198 }
199
200 fn supports_session_catalog(&self) -> bool {
203 false
204 }
205
206 async fn catalog_for_request(&self, _request: &Request) -> Result<Option<Catalog>> {
208 Ok(None)
209 }
210
211 async fn close(&self) -> Result<()> {
213 Ok(())
214 }
215}
216
217impl From<Infallible> for Error {
218 fn from(_value: Infallible) -> Self {
219 Error::internal("unreachable infallible error")
220 }
221}