1use std::sync::Arc;
2use std::time::SystemTime;
3
4use prost_types::{Struct, Timestamp, Value};
5use serde::Serialize;
6use tonic::codegen::async_trait;
7use tonic::{Request as GrpcRequest, Response as GrpcResponse, Status};
8
9use crate::api::{RuntimeMetadata, Subject, scope_request_context};
10use crate::error::Result as ProviderResult;
11use crate::generated::v1::{self as pb};
12use crate::protocol;
13use crate::rpc_status::rpc_status;
14
15pub type AgentJson = serde_json::Value;
17
18#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
19#[repr(i32)]
20pub enum AgentMessagePartType {
22 #[default]
23 Unspecified = 0,
25 Text = 1,
27 Json = 2,
29 ToolCall = 3,
31 ToolResult = 4,
33 ImageRef = 5,
35}
36
37impl AgentMessagePartType {
38 pub const fn as_i32(self) -> i32 {
40 self as i32
41 }
42
43 pub const fn from_i32_lossy(value: i32) -> Self {
46 match value {
47 1 => Self::Text,
48 2 => Self::Json,
49 3 => Self::ToolCall,
50 4 => Self::ToolResult,
51 5 => Self::ImageRef,
52 _ => Self::Unspecified,
53 }
54 }
55}
56
57impl TryFrom<i32> for AgentMessagePartType {
58 type Error = crate::Error;
59
60 fn try_from(value: i32) -> ProviderResult<Self> {
61 match value {
62 0 => Ok(Self::Unspecified),
63 1 => Ok(Self::Text),
64 2 => Ok(Self::Json),
65 3 => Ok(Self::ToolCall),
66 4 => Ok(Self::ToolResult),
67 5 => Ok(Self::ImageRef),
68 _ => Err(crate::Error::bad_request(format!(
69 "unknown agent message part type {value}"
70 ))),
71 }
72 }
73}
74
75#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
76#[repr(i32)]
77pub enum AgentToolSourceMode {
79 #[default]
80 Unspecified = 0,
82 Catalog = 2,
84 None = 3,
86}
87
88impl AgentToolSourceMode {
89 pub const fn as_i32(self) -> i32 {
91 self as i32
92 }
93
94 pub const fn from_i32_lossy(value: i32) -> Self {
97 match value {
98 2 => Self::Catalog,
99 3 => Self::None,
100 _ => Self::Unspecified,
101 }
102 }
103}
104
105impl TryFrom<i32> for AgentToolSourceMode {
106 type Error = crate::Error;
107
108 fn try_from(value: i32) -> ProviderResult<Self> {
109 match value {
110 0 => Ok(Self::Unspecified),
111 2 => Ok(Self::Catalog),
112 3 => Ok(Self::None),
113 _ => Err(crate::Error::bad_request(format!(
114 "unknown agent tool source mode {value}"
115 ))),
116 }
117 }
118}
119
120#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
121#[repr(i32)]
122pub enum AgentExecutionStatus {
124 #[default]
125 Unspecified = 0,
127 Pending = 1,
129 Running = 2,
131 Succeeded = 3,
133 Failed = 4,
135 Canceled = 5,
137 WaitingForInput = 6,
139}
140
141impl AgentExecutionStatus {
142 pub const fn as_i32(self) -> i32 {
144 self as i32
145 }
146
147 pub const fn from_i32_lossy(value: i32) -> Self {
150 match value {
151 1 => Self::Pending,
152 2 => Self::Running,
153 3 => Self::Succeeded,
154 4 => Self::Failed,
155 5 => Self::Canceled,
156 6 => Self::WaitingForInput,
157 _ => Self::Unspecified,
158 }
159 }
160}
161
162impl TryFrom<i32> for AgentExecutionStatus {
163 type Error = crate::Error;
164
165 fn try_from(value: i32) -> ProviderResult<Self> {
166 match value {
167 0 => Ok(Self::Unspecified),
168 1 => Ok(Self::Pending),
169 2 => Ok(Self::Running),
170 3 => Ok(Self::Succeeded),
171 4 => Ok(Self::Failed),
172 5 => Ok(Self::Canceled),
173 6 => Ok(Self::WaitingForInput),
174 _ => Err(crate::Error::bad_request(format!(
175 "unknown agent execution status {value}"
176 ))),
177 }
178 }
179}
180
181#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
182#[repr(i32)]
183pub enum AgentSessionState {
185 #[default]
186 Unspecified = 0,
188 Active = 1,
190 Archived = 2,
192}
193
194impl AgentSessionState {
195 pub const fn as_i32(self) -> i32 {
197 self as i32
198 }
199
200 pub const fn from_i32_lossy(value: i32) -> Self {
203 match value {
204 1 => Self::Active,
205 2 => Self::Archived,
206 _ => Self::Unspecified,
207 }
208 }
209}
210
211impl TryFrom<i32> for AgentSessionState {
212 type Error = crate::Error;
213
214 fn try_from(value: i32) -> ProviderResult<Self> {
215 match value {
216 0 => Ok(Self::Unspecified),
217 1 => Ok(Self::Active),
218 2 => Ok(Self::Archived),
219 _ => Err(crate::Error::bad_request(format!(
220 "unknown agent session state {value}"
221 ))),
222 }
223 }
224}
225
226#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
227#[repr(i32)]
228pub enum AgentInteractionType {
230 #[default]
231 Unspecified = 0,
233 Approval = 1,
235 Clarification = 2,
237 Input = 3,
239}
240
241impl AgentInteractionType {
242 pub const fn as_i32(self) -> i32 {
244 self as i32
245 }
246
247 pub const fn from_i32_lossy(value: i32) -> Self {
250 match value {
251 1 => Self::Approval,
252 2 => Self::Clarification,
253 3 => Self::Input,
254 _ => Self::Unspecified,
255 }
256 }
257}
258
259impl TryFrom<i32> for AgentInteractionType {
260 type Error = crate::Error;
261
262 fn try_from(value: i32) -> ProviderResult<Self> {
263 match value {
264 0 => Ok(Self::Unspecified),
265 1 => Ok(Self::Approval),
266 2 => Ok(Self::Clarification),
267 3 => Ok(Self::Input),
268 _ => Err(crate::Error::bad_request(format!(
269 "unknown agent interaction type {value}"
270 ))),
271 }
272 }
273}
274
275#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
276#[repr(i32)]
277pub enum AgentInteractionState {
279 #[default]
280 Unspecified = 0,
282 Pending = 1,
284 Resolved = 2,
286 Canceled = 3,
288}
289
290impl AgentInteractionState {
291 pub const fn as_i32(self) -> i32 {
293 self as i32
294 }
295
296 pub const fn from_i32_lossy(value: i32) -> Self {
299 match value {
300 1 => Self::Pending,
301 2 => Self::Resolved,
302 3 => Self::Canceled,
303 _ => Self::Unspecified,
304 }
305 }
306}
307
308impl TryFrom<i32> for AgentInteractionState {
309 type Error = crate::Error;
310
311 fn try_from(value: i32) -> ProviderResult<Self> {
312 match value {
313 0 => Ok(Self::Unspecified),
314 1 => Ok(Self::Pending),
315 2 => Ok(Self::Resolved),
316 3 => Ok(Self::Canceled),
317 _ => Err(crate::Error::bad_request(format!(
318 "unknown agent interaction state {value}"
319 ))),
320 }
321 }
322}
323
324#[derive(Debug, Clone, Default, PartialEq)]
325pub struct AgentMessage {
327 pub role: String,
329 pub text: String,
331 pub parts: Vec<AgentMessagePart>,
333 pub metadata: Option<AgentJson>,
335}
336
337#[derive(Debug, Clone, Default, PartialEq)]
338pub struct AgentMessagePartToolCall {
340 pub id: String,
342 pub tool_id: String,
344 pub arguments: Option<AgentJson>,
346}
347
348#[derive(Debug, Clone, Default, PartialEq)]
349pub struct AgentMessagePartToolResult {
351 pub tool_call_id: String,
353 pub status: i32,
355 pub content: String,
357 pub output: Option<AgentJson>,
359}
360
361#[derive(Debug, Clone, Default, PartialEq, Eq)]
362pub struct AgentMessagePartImageRef {
364 pub uri: String,
366 pub mime_type: String,
368}
369
370#[derive(Debug, Clone, Default, PartialEq)]
371pub struct AgentMessagePart {
373 pub r#type: AgentMessagePartType,
375 pub text: String,
377 pub json: Option<AgentJson>,
379 pub tool_call: Option<AgentMessagePartToolCall>,
381 pub tool_result: Option<AgentMessagePartToolResult>,
383 pub image_ref: Option<AgentMessagePartImageRef>,
385}
386
387#[derive(Debug, Clone, Default, PartialEq, Eq)]
388pub struct AgentPreparedWorkspace {
390 pub root: String,
392 pub cwd: String,
394}
395
396#[derive(Debug, Clone, Default, PartialEq, Eq)]
397pub struct AgentToolRef {
399 pub app: String,
401 pub operation: String,
403 pub connection: String,
405 pub instance: String,
407 pub title: String,
409 pub description: String,
411 pub credential_mode: String,
413 pub system: String,
415 pub run_as: Option<Subject>,
417}
418
419#[derive(Debug, Clone, Default, PartialEq)]
420pub struct AgentToolConfig {
422 pub source: Option<AgentToolConfigSource>,
424}
425
426#[derive(Debug, Clone, PartialEq)]
427pub enum AgentToolConfigSource {
429 None(AgentNoTools),
431 Catalog(AgentCatalogToolConfig),
433}
434
435#[derive(Debug, Clone, Default, PartialEq, Eq)]
436pub struct AgentNoTools {}
437
438#[derive(Debug, Clone, Default, PartialEq)]
439pub struct AgentCatalogToolConfig {
441 pub refs: Vec<AgentToolRef>,
443 pub tools: Vec<ListedAgentTool>,
445}
446
447impl AgentMessage {
448 pub fn with_metadata<T: Serialize>(mut self, value: T) -> ProviderResult<Self> {
450 self.metadata = Some(protocol::json_from_serializable(value)?);
451 Ok(self)
452 }
453
454 pub fn user_text(text: impl Into<String>) -> Self {
456 Self {
457 role: "user".to_string(),
458 text: text.into(),
459 ..Default::default()
460 }
461 }
462}
463
464impl AgentMessagePart {
465 pub fn json<T: Serialize>(value: T) -> ProviderResult<Self> {
467 Ok(Self {
468 r#type: AgentMessagePartType::Json,
469 json: Some(protocol::json_from_serializable(value)?),
470 ..Default::default()
471 })
472 }
473}
474
475impl AgentMessagePartToolCall {
476 pub fn with_arguments<T: Serialize>(mut self, value: T) -> ProviderResult<Self> {
478 self.arguments = Some(protocol::json_from_serializable(value)?);
479 Ok(self)
480 }
481}
482
483impl AgentMessagePartToolResult {
484 pub fn with_output<T: Serialize>(mut self, value: T) -> ProviderResult<Self> {
486 self.output = Some(protocol::json_from_serializable(value)?);
487 Ok(self)
488 }
489}
490
491#[derive(Clone, Debug, Default, PartialEq, Eq)]
493pub struct AgentWorkspace {
494 pub checkouts: Vec<AgentWorkspaceGitCheckout>,
496 pub cwd: String,
498}
499
500#[derive(Clone, Debug, Default, PartialEq, Eq)]
502pub struct AgentWorkspaceGitCheckout {
503 pub url: String,
505 pub reference: String,
507 pub path: String,
509}
510
511#[derive(Debug, Clone, Default, PartialEq, Eq)]
512pub struct AgentProviderCapabilities {
514 pub streaming_text: bool,
516 pub tool_calls: bool,
518 pub parallel_tool_calls: bool,
520 pub interactions: bool,
522 pub resumable_turns: bool,
524 pub reasoning_summaries: bool,
526 pub bounded_list_hydration: bool,
528 pub supported_tool_sources: Vec<AgentToolSourceMode>,
530 pub supports_session_start: bool,
532 pub supports_prepared_workspace: bool,
534}
535
536#[derive(Debug, Clone, Default, PartialEq, Eq)]
537pub struct GetAgentProviderCapabilitiesRequest {}
539
540#[derive(Debug, Clone, Default, PartialEq)]
541pub struct AgentInteraction {
543 pub id: String,
545 pub r#type: AgentInteractionType,
547 pub state: AgentInteractionState,
549 pub title: String,
551 pub prompt: String,
553 pub request: Option<AgentJson>,
555 pub resolution: Option<AgentJson>,
557 pub created_at: Option<SystemTime>,
559 pub resolved_at: Option<SystemTime>,
561 pub turn_id: String,
563 pub session_id: String,
565}
566
567#[derive(Debug, Clone, Default, PartialEq)]
568pub struct AgentSession {
570 pub id: String,
572 pub provider_name: String,
574 pub model: String,
576 pub client_ref: String,
578 pub state: AgentSessionState,
580 pub metadata: Option<AgentJson>,
582 pub created_by_subject_id: Option<String>,
584 pub created_at: Option<SystemTime>,
586 pub updated_at: Option<SystemTime>,
588 pub last_turn_at: Option<SystemTime>,
590}
591
592#[derive(Debug, Clone, Default, PartialEq)]
594pub struct CreateAgentProviderSessionRequest {
595 pub idempotency_key: String,
597 pub model: String,
599 pub client_ref: String,
601 pub metadata: Option<AgentJson>,
603 pub session_start: Option<AgentSessionStartConfig>,
605 pub prepared_workspace: Option<AgentPreparedWorkspace>,
607 pub tools: Option<AgentToolConfig>,
609}
610
611#[derive(Debug, Clone, Default, PartialEq, Eq)]
612pub struct AgentSessionStartConfig {
614 pub hooks: Vec<AgentSessionStartHook>,
616}
617
618#[derive(Debug, Clone, Default, PartialEq, Eq)]
619pub struct AgentSessionStartHook {
621 pub id: String,
623 pub r#type: String,
625 pub command: Vec<String>,
627 pub cwd: String,
629 pub timeout: String,
631 pub env: std::collections::HashMap<String, String>,
633 pub output: Option<AgentSessionStartHookOutput>,
635}
636
637#[derive(Debug, Clone, Default, PartialEq, Eq)]
638pub struct AgentSessionStartHookOutput {
640 pub additional_context: bool,
642 pub metadata: bool,
644}
645
646#[derive(Debug, Clone, Default, PartialEq, Eq)]
647pub struct GetAgentProviderSessionRequest {
649 pub provider_name: String,
651 pub session_id: String,
653}
654
655#[derive(Debug, Clone, Default, PartialEq, Eq)]
656pub struct ListAgentProviderSessionsRequest {
658 pub provider_name: String,
660 pub session_ids: Vec<String>,
662 pub state: AgentSessionState,
664 pub limit: i32,
666 pub summary_only: bool,
668}
669
670#[derive(Debug, Clone, Default, PartialEq)]
671pub struct ListAgentProviderSessionsResponse {
673 pub sessions: Vec<AgentSession>,
675}
676
677#[derive(Debug, Clone, Default, PartialEq)]
678pub struct UpdateAgentProviderSessionRequest {
680 pub provider_name: String,
682 pub session_id: String,
684 pub client_ref: String,
686 pub state: AgentSessionState,
688 pub metadata: Option<AgentJson>,
690}
691
692#[derive(Debug, Clone, Default, PartialEq)]
693pub struct AgentTurn {
695 pub id: String,
697 pub session_id: String,
699 pub provider_name: String,
701 pub model: String,
703 pub status: AgentExecutionStatus,
705 pub messages: Vec<AgentMessage>,
707 pub output: Option<AgentTurnOutput>,
709 pub status_message: String,
711 pub created_by_subject_id: Option<String>,
713 pub created_at: Option<SystemTime>,
715 pub started_at: Option<SystemTime>,
717 pub completed_at: Option<SystemTime>,
719 pub execution_ref: String,
721}
722
723#[derive(Debug, Clone, PartialEq)]
724pub enum AgentTurnOutput {
726 Text(AgentTurnTextOutput),
728 Structured(AgentTurnStructuredOutput),
730}
731
732#[derive(Debug, Clone, Default, PartialEq, Eq)]
733pub struct AgentTurnTextOutput {
735 pub text: String,
737}
738
739#[derive(Debug, Clone, Default, PartialEq)]
740pub struct AgentTurnStructuredOutput {
742 pub text: String,
744 pub value: Option<AgentJson>,
746}
747
748#[derive(Debug, Clone, Default, PartialEq)]
749pub struct AgentTurnDisplay {
751 pub kind: String,
753 pub phase: String,
755 pub text: String,
757 pub label: String,
759 pub r#ref: String,
761 pub parent_ref: String,
763 pub input: Option<AgentJson>,
765 pub output: Option<AgentJson>,
767 pub error: Option<AgentJson>,
769 pub action: String,
771 pub format: String,
773 pub language: String,
775}
776
777#[derive(Debug, Clone, PartialEq)]
778pub struct CreateAgentProviderTurnRequest {
780 pub provider_name: String,
782 pub turn_id: String,
784 pub session_id: String,
786 pub idempotency_key: String,
788 pub model: String,
790 pub messages: Vec<AgentMessage>,
792 pub output: AgentOutput,
794 pub metadata: Option<AgentJson>,
796 pub execution_ref: String,
798 pub model_options: Option<AgentJson>,
800 pub timeout_seconds: i32,
802 pub context: Option<pb::RequestContext>,
804}
805
806#[derive(Debug, Clone, PartialEq)]
807pub enum AgentOutput {
809 Text(AgentTextOutput),
811 Structured(AgentStructuredOutput),
813}
814
815#[derive(Debug, Clone, Default, PartialEq, Eq)]
816pub struct AgentTextOutput {}
818
819#[derive(Debug, Clone, PartialEq)]
820pub struct AgentStructuredOutput {
822 pub schema: AgentJson,
824}
825
826impl AgentOutput {
827 pub fn text() -> Self {
829 Self::Text(AgentTextOutput {})
830 }
831
832 pub fn structured_schema<T: Serialize>(schema: T) -> ProviderResult<Self> {
834 Ok(Self::Structured(AgentStructuredOutput {
835 schema: protocol::json_from_serializable(schema)?,
836 }))
837 }
838}
839
840#[derive(Debug, Clone, Default, PartialEq, Eq)]
841pub struct GetAgentProviderTurnRequest {
843 pub provider_name: String,
845 pub turn_id: String,
847}
848
849#[derive(Debug, Clone, Default, PartialEq, Eq)]
850pub struct ListAgentProviderTurnsRequest {
852 pub provider_name: String,
854 pub session_id: String,
856 pub turn_ids: Vec<String>,
858 pub status: AgentExecutionStatus,
860 pub limit: i32,
862 pub summary_only: bool,
864}
865
866#[derive(Debug, Clone, Default, PartialEq)]
867pub struct ListAgentProviderTurnsResponse {
869 pub turns: Vec<AgentTurn>,
871}
872
873#[derive(Debug, Clone, Default, PartialEq, Eq)]
874pub struct CancelAgentProviderTurnRequest {
876 pub provider_name: String,
878 pub turn_id: String,
880 pub reason: String,
882}
883
884#[derive(Debug, Clone, Default, PartialEq)]
885pub struct AgentTurnEvent {
887 pub id: String,
889 pub turn_id: String,
891 pub seq: i64,
893 pub r#type: String,
895 pub source: String,
897 pub visibility: String,
899 pub data: Option<AgentJson>,
901 pub created_at: Option<SystemTime>,
903 pub display: Option<AgentTurnDisplay>,
905}
906
907#[derive(Debug, Clone, Default, PartialEq, Eq)]
908pub struct ListAgentProviderTurnEventsRequest {
910 pub provider_name: String,
912 pub turn_id: String,
914 pub after_seq: i64,
916 pub limit: i32,
918}
919
920#[derive(Debug, Clone, Default, PartialEq)]
921pub struct ListAgentProviderTurnEventsResponse {
923 pub events: Vec<AgentTurnEvent>,
925}
926
927#[derive(Debug, Clone, Default, PartialEq, Eq)]
928pub struct GetAgentProviderInteractionRequest {
930 pub interaction_id: String,
932}
933
934#[derive(Debug, Clone, Default, PartialEq, Eq)]
935pub struct ListAgentProviderInteractionsRequest {
937 pub provider_name: String,
939 pub turn_id: String,
941}
942
943#[derive(Debug, Clone, Default, PartialEq)]
944pub struct ListAgentProviderInteractionsResponse {
946 pub interactions: Vec<AgentInteraction>,
948}
949
950#[derive(Debug, Clone, Default, PartialEq)]
951pub struct ResolveAgentProviderInteractionRequest {
953 pub provider_name: String,
955 pub interaction_id: String,
957 pub resolution: Option<AgentJson>,
959}
960
961#[derive(Debug, Clone, Default, PartialEq, Eq)]
962pub struct AgentToolAnnotations {
964 pub read_only_hint: Option<bool>,
966 pub idempotent_hint: Option<bool>,
968 pub destructive_hint: Option<bool>,
970 pub open_world_hint: Option<bool>,
972}
973
974#[derive(Debug, Clone, Default, PartialEq)]
975pub struct ListedAgentTool {
977 pub id: String,
979 pub mcp_name: String,
981 pub title: String,
983 pub description: String,
985 pub input_schema: String,
987 pub output_schema: String,
989 pub annotations: Option<AgentToolAnnotations>,
991 pub r#ref: Option<AgentToolRef>,
993 pub tags: Vec<String>,
995 pub search_text: String,
997}
998
999pub fn new_agent_message(input: AgentMessage) -> ProviderResult<AgentMessage> {
1001 Ok(AgentMessage {
1002 role: input.role,
1003 text: input.text,
1004 parts: input
1005 .parts
1006 .into_iter()
1007 .map(new_agent_message_part)
1008 .collect::<ProviderResult<Vec<_>>>()?,
1009 metadata: input.metadata,
1010 })
1011}
1012
1013pub fn new_agent_message_part(input: AgentMessagePart) -> ProviderResult<AgentMessagePart> {
1015 let mut part_type = input.r#type;
1016 if part_type == AgentMessagePartType::Unspecified {
1017 part_type = infer_agent_message_part_type(&input);
1018 }
1019 Ok(AgentMessagePart {
1020 r#type: part_type,
1021 text: input.text,
1022 json: input.json,
1023 tool_call: input.tool_call.map(new_agent_tool_call).transpose()?,
1024 tool_result: input.tool_result.map(new_agent_tool_result).transpose()?,
1025 image_ref: input.image_ref.map(new_agent_image_ref),
1026 })
1027}
1028
1029pub fn new_agent_tool_call(
1031 input: AgentMessagePartToolCall,
1032) -> ProviderResult<AgentMessagePartToolCall> {
1033 Ok(AgentMessagePartToolCall {
1034 id: input.id,
1035 tool_id: input.tool_id,
1036 arguments: input.arguments,
1037 })
1038}
1039
1040pub fn new_agent_tool_result(
1042 input: AgentMessagePartToolResult,
1043) -> ProviderResult<AgentMessagePartToolResult> {
1044 Ok(AgentMessagePartToolResult {
1045 tool_call_id: input.tool_call_id,
1046 status: input.status,
1047 content: input.content,
1048 output: input.output,
1049 })
1050}
1051
1052pub fn new_agent_image_ref(input: AgentMessagePartImageRef) -> AgentMessagePartImageRef {
1054 AgentMessagePartImageRef {
1055 uri: input.uri,
1056 mime_type: input.mime_type,
1057 }
1058}
1059
1060pub fn new_agent_tool_ref(input: AgentToolRef) -> AgentToolRef {
1062 AgentToolRef {
1063 app: input.app,
1064 operation: input.operation,
1065 connection: input.connection,
1066 instance: input.instance,
1067 title: input.title,
1068 description: input.description,
1069 credential_mode: input.credential_mode,
1070 system: input.system,
1071 run_as: input.run_as,
1072 }
1073}
1074
1075fn infer_agent_message_part_type(input: &AgentMessagePart) -> AgentMessagePartType {
1076 if input.tool_call.is_some() {
1077 AgentMessagePartType::ToolCall
1078 } else if input.tool_result.is_some() {
1079 AgentMessagePartType::ToolResult
1080 } else if input.image_ref.is_some() {
1081 AgentMessagePartType::ImageRef
1082 } else if input.json.is_some() {
1083 AgentMessagePartType::Json
1084 } else if !input.text.is_empty() {
1085 AgentMessagePartType::Text
1086 } else {
1087 AgentMessagePartType::Unspecified
1088 }
1089}
1090
1091fn json_from_struct(value: Option<Struct>) -> Option<AgentJson> {
1092 value.map(|value| protocol::json_from_struct(&value))
1093}
1094
1095fn struct_from_json(value: Option<AgentJson>) -> ProviderResult<Option<Struct>> {
1096 value.map(protocol::struct_from_json).transpose()
1097}
1098
1099fn value_from_json(value: Option<AgentJson>) -> Option<Value> {
1100 value.map(protocol::value_from_json)
1101}
1102
1103fn timestamp_from_time(value: Option<SystemTime>) -> Option<Timestamp> {
1104 value.map(protocol::timestamp_from_system_time)
1105}
1106
1107pub(crate) fn agent_tool_ref_from_proto(value: pb::AgentToolRef) -> AgentToolRef {
1108 AgentToolRef {
1109 app: value.app,
1110 operation: value.operation,
1111 connection: value.connection,
1112 instance: value.instance,
1113 title: value.title,
1114 description: value.description,
1115 credential_mode: value.credential_mode,
1116 system: value.system,
1117 run_as: agent_run_as_context_from_proto(value.run_as),
1118 }
1119}
1120
1121fn agent_run_as_context_from_proto(value: Option<pb::SubjectContext>) -> Option<Subject> {
1122 value.map(|value| Subject {
1123 id: value.id,
1124 email: value.email,
1125 display_name: value.display_name,
1126 })
1127}
1128
1129pub(crate) fn message_from_proto(value: pb::AgentMessage) -> AgentMessage {
1130 AgentMessage {
1131 role: value.role,
1132 text: value.text,
1133 parts: value
1134 .parts
1135 .into_iter()
1136 .map(message_part_from_proto)
1137 .collect(),
1138 metadata: json_from_struct(value.metadata),
1139 }
1140}
1141
1142pub(crate) fn message_to_proto(value: AgentMessage) -> ProviderResult<pb::AgentMessage> {
1143 Ok(pb::AgentMessage {
1144 role: value.role,
1145 text: value.text,
1146 parts: value
1147 .parts
1148 .into_iter()
1149 .map(message_part_to_proto)
1150 .collect::<ProviderResult<Vec<_>>>()?,
1151 metadata: struct_from_json(value.metadata)?,
1152 })
1153}
1154
1155fn message_part_from_proto(value: pb::AgentMessagePart) -> AgentMessagePart {
1156 AgentMessagePart {
1157 r#type: AgentMessagePartType::from_i32_lossy(value.r#type),
1158 text: value.text,
1159 json: json_from_struct(value.json),
1160 tool_call: value.tool_call.map(|value| AgentMessagePartToolCall {
1161 id: value.id,
1162 tool_id: value.tool_id,
1163 arguments: json_from_struct(value.arguments),
1164 }),
1165 tool_result: value.tool_result.map(|value| AgentMessagePartToolResult {
1166 tool_call_id: value.tool_call_id,
1167 status: value.status,
1168 content: value.content,
1169 output: json_from_struct(value.output),
1170 }),
1171 image_ref: value.image_ref.map(|value| AgentMessagePartImageRef {
1172 uri: value.uri,
1173 mime_type: value.mime_type,
1174 }),
1175 }
1176}
1177
1178fn message_part_to_proto(value: AgentMessagePart) -> ProviderResult<pb::AgentMessagePart> {
1179 Ok(pb::AgentMessagePart {
1180 r#type: value.r#type.as_i32(),
1181 text: value.text,
1182 json: struct_from_json(value.json)?,
1183 tool_call: value
1184 .tool_call
1185 .map(|value| -> ProviderResult<pb::AgentMessagePartToolCall> {
1186 Ok(pb::AgentMessagePartToolCall {
1187 id: value.id,
1188 tool_id: value.tool_id,
1189 arguments: struct_from_json(value.arguments)?,
1190 })
1191 })
1192 .transpose()?,
1193 tool_result: value
1194 .tool_result
1195 .map(|value| -> ProviderResult<pb::AgentMessagePartToolResult> {
1196 Ok(pb::AgentMessagePartToolResult {
1197 tool_call_id: value.tool_call_id,
1198 status: value.status,
1199 content: value.content,
1200 output: struct_from_json(value.output)?,
1201 })
1202 })
1203 .transpose()?,
1204 image_ref: value.image_ref.map(|value| pb::AgentMessagePartImageRef {
1205 uri: value.uri,
1206 mime_type: value.mime_type,
1207 }),
1208 })
1209}
1210
1211fn session_to_proto(value: AgentSession) -> ProviderResult<pb::AgentSession> {
1212 Ok(pb::AgentSession {
1213 id: value.id,
1214 provider_name: value.provider_name,
1215 model: value.model,
1216 client_ref: value.client_ref,
1217 state: value.state.as_i32(),
1218 metadata: struct_from_json(value.metadata)?,
1219 created_by_subject_id: value.created_by_subject_id.clone().unwrap_or_default(),
1220 created_at: timestamp_from_time(value.created_at),
1221 updated_at: timestamp_from_time(value.updated_at),
1222 last_turn_at: timestamp_from_time(value.last_turn_at),
1223 })
1224}
1225
1226fn turn_to_proto(value: AgentTurn) -> ProviderResult<pb::AgentTurn> {
1227 Ok(pb::AgentTurn {
1228 id: value.id,
1229 session_id: value.session_id,
1230 provider_name: value.provider_name,
1231 model: value.model,
1232 status: value.status.as_i32(),
1233 messages: value
1234 .messages
1235 .into_iter()
1236 .map(message_to_proto)
1237 .collect::<ProviderResult<Vec<_>>>()?,
1238 output: agent_turn_output_to_proto(value.output)?,
1239 status_message: value.status_message,
1240 created_by_subject_id: value.created_by_subject_id.clone().unwrap_or_default(),
1241 created_at: timestamp_from_time(value.created_at),
1242 started_at: timestamp_from_time(value.started_at),
1243 completed_at: timestamp_from_time(value.completed_at),
1244 execution_ref: value.execution_ref,
1245 })
1246}
1247
1248fn display_to_proto(value: AgentTurnDisplay) -> pb::AgentTurnDisplay {
1249 pb::AgentTurnDisplay {
1250 kind: value.kind,
1251 phase: value.phase,
1252 text: value.text,
1253 label: value.label,
1254 r#ref: value.r#ref,
1255 parent_ref: value.parent_ref,
1256 input: value_from_json(value.input),
1257 output: value_from_json(value.output),
1258 error: value_from_json(value.error),
1259 action: value.action,
1260 format: value.format,
1261 language: value.language,
1262 }
1263}
1264
1265fn agent_turn_output_to_proto(
1266 value: Option<AgentTurnOutput>,
1267) -> ProviderResult<Option<pb::agent_turn::Output>> {
1268 match value {
1269 Some(AgentTurnOutput::Text(output)) => Ok(Some(pb::agent_turn::Output::Text(
1270 pb::AgentTurnTextOutput { text: output.text },
1271 ))),
1272 Some(AgentTurnOutput::Structured(output)) => Ok(Some(pb::agent_turn::Output::Structured(
1273 pb::AgentTurnStructuredOutput {
1274 text: output.text,
1275 value: struct_from_json(output.value)?,
1276 },
1277 ))),
1278 None => Ok(None),
1279 }
1280}
1281
1282fn agent_output_from_proto(value: Option<pb::AgentOutput>) -> ProviderResult<Option<AgentOutput>> {
1283 match value.and_then(|output| output.kind) {
1284 Some(pb::agent_output::Kind::Text(_)) => Ok(Some(AgentOutput::Text(AgentTextOutput {}))),
1285 Some(pb::agent_output::Kind::Structured(output)) => {
1286 let schema = json_from_struct(output.schema)
1287 .ok_or_else(|| crate::Error::bad_request("output.structured.schema is required"))?;
1288 Ok(Some(AgentOutput::Structured(AgentStructuredOutput {
1289 schema,
1290 })))
1291 }
1292 None => Ok(None),
1293 }
1294}
1295
1296fn required_agent_output_from_proto(value: Option<pb::AgentOutput>) -> ProviderResult<AgentOutput> {
1297 agent_output_from_proto(value)?
1298 .ok_or_else(|| crate::Error::bad_request("create turn output is required"))
1299}
1300
1301fn event_to_proto(value: AgentTurnEvent) -> ProviderResult<pb::AgentTurnEvent> {
1302 Ok(pb::AgentTurnEvent {
1303 id: value.id,
1304 turn_id: value.turn_id,
1305 seq: value.seq,
1306 r#type: value.r#type,
1307 source: value.source,
1308 visibility: value.visibility,
1309 data: struct_from_json(value.data)?,
1310 created_at: timestamp_from_time(value.created_at),
1311 display: value.display.map(display_to_proto),
1312 })
1313}
1314
1315fn interaction_to_proto(value: AgentInteraction) -> ProviderResult<pb::AgentInteraction> {
1316 Ok(pb::AgentInteraction {
1317 id: value.id,
1318 r#type: value.r#type.as_i32(),
1319 state: value.state.as_i32(),
1320 title: value.title,
1321 prompt: value.prompt,
1322 request: struct_from_json(value.request)?,
1323 resolution: struct_from_json(value.resolution)?,
1324 created_at: timestamp_from_time(value.created_at),
1325 resolved_at: timestamp_from_time(value.resolved_at),
1326 turn_id: value.turn_id,
1327 session_id: value.session_id,
1328 })
1329}
1330
1331fn capabilities_to_proto(value: AgentProviderCapabilities) -> pb::AgentProviderCapabilities {
1332 pb::AgentProviderCapabilities {
1333 streaming_text: value.streaming_text,
1334 tool_calls: value.tool_calls,
1335 parallel_tool_calls: value.parallel_tool_calls,
1336 interactions: value.interactions,
1337 resumable_turns: value.resumable_turns,
1338 reasoning_summaries: value.reasoning_summaries,
1339 bounded_list_hydration: value.bounded_list_hydration,
1340 supported_tool_sources: value
1341 .supported_tool_sources
1342 .into_iter()
1343 .map(AgentToolSourceMode::as_i32)
1344 .collect(),
1345 supports_session_start: value.supports_session_start,
1346 supports_prepared_workspace: value.supports_prepared_workspace,
1347 }
1348}
1349
1350fn create_session_request_from_proto(
1351 value: pb::CreateAgentProviderSessionRequest,
1352) -> CreateAgentProviderSessionRequest {
1353 CreateAgentProviderSessionRequest {
1354 idempotency_key: value.idempotency_key,
1355 model: value.model,
1356 client_ref: value.client_ref,
1357 metadata: json_from_struct(value.metadata),
1358 session_start: value.session_start.map(|value| AgentSessionStartConfig {
1359 hooks: value
1360 .hooks
1361 .into_iter()
1362 .map(|hook| AgentSessionStartHook {
1363 id: hook.id,
1364 r#type: hook.r#type,
1365 command: hook.command,
1366 cwd: hook.cwd,
1367 timeout: hook.timeout,
1368 env: hook.env.into_iter().collect(),
1369 output: hook.output.map(|output| AgentSessionStartHookOutput {
1370 additional_context: output.additional_context,
1371 metadata: output.metadata,
1372 }),
1373 })
1374 .collect(),
1375 }),
1376 prepared_workspace: value
1377 .prepared_workspace
1378 .map(|value| AgentPreparedWorkspace {
1379 root: value.root,
1380 cwd: value.cwd,
1381 }),
1382 tools: value.tools.map(agent_tool_config_from_proto),
1383 }
1384}
1385
1386fn create_turn_request_from_proto(
1387 value: pb::CreateAgentProviderTurnRequest,
1388) -> ProviderResult<CreateAgentProviderTurnRequest> {
1389 if value.timeout_seconds < 0 {
1390 return Err(crate::Error::bad_request(
1391 "agent create turn timeout_seconds must not be negative",
1392 ));
1393 }
1394 Ok(CreateAgentProviderTurnRequest {
1395 provider_name: value.provider_name,
1396 turn_id: value.turn_id,
1397 session_id: value.session_id,
1398 idempotency_key: value.idempotency_key,
1399 model: value.model,
1400 messages: value.messages.into_iter().map(message_from_proto).collect(),
1401 output: required_agent_output_from_proto(value.output)?,
1402 metadata: json_from_struct(value.metadata),
1403 execution_ref: value.execution_ref,
1404 model_options: json_from_struct(value.model_options),
1405 timeout_seconds: value.timeout_seconds,
1406 context: value.context,
1407 })
1408}
1409
1410fn listed_tool_from_proto(value: pb::ListedAgentTool) -> ListedAgentTool {
1411 ListedAgentTool {
1412 id: value.id,
1413 mcp_name: value.mcp_name,
1414 title: value.title,
1415 description: value.description,
1416 input_schema: value.input_schema,
1417 output_schema: value.output_schema,
1418 annotations: value.annotations.map(|annotations| AgentToolAnnotations {
1419 read_only_hint: annotations.read_only_hint,
1420 idempotent_hint: annotations.idempotent_hint,
1421 destructive_hint: annotations.destructive_hint,
1422 open_world_hint: annotations.open_world_hint,
1423 }),
1424 r#ref: value.r#ref.map(agent_tool_ref_from_proto),
1425 tags: value.tags,
1426 search_text: value.search_text,
1427 }
1428}
1429
1430fn agent_tool_config_from_proto(value: pb::AgentToolConfig) -> AgentToolConfig {
1431 let source = match value.source {
1432 Some(pb::agent_tool_config::Source::None(_)) => {
1433 Some(AgentToolConfigSource::None(AgentNoTools {}))
1434 }
1435 Some(pb::agent_tool_config::Source::Catalog(catalog)) => {
1436 Some(AgentToolConfigSource::Catalog(AgentCatalogToolConfig {
1437 refs: catalog
1438 .refs
1439 .into_iter()
1440 .map(agent_tool_ref_from_proto)
1441 .collect(),
1442 tools: catalog
1443 .tools
1444 .into_iter()
1445 .map(listed_tool_from_proto)
1446 .collect(),
1447 }))
1448 }
1449 None => None,
1450 };
1451 AgentToolConfig { source }
1452}
1453
1454#[async_trait]
1455pub trait AgentProvider: Send + Sync + 'static {
1457 async fn configure(
1459 &self,
1460 _name: &str,
1461 _config: serde_json::Map<String, serde_json::Value>,
1462 ) -> ProviderResult<()> {
1463 Ok(())
1464 }
1465
1466 fn metadata(&self) -> Option<RuntimeMetadata> {
1468 None
1469 }
1470
1471 fn warnings(&self) -> Vec<String> {
1473 Vec::new()
1474 }
1475
1476 async fn health_check(&self) -> ProviderResult<()> {
1478 Ok(())
1479 }
1480
1481 async fn start(&self) -> ProviderResult<()> {
1483 Ok(())
1484 }
1485
1486 async fn close(&self) -> ProviderResult<()> {
1488 Ok(())
1489 }
1490
1491 async fn create_session(
1497 &self,
1498 _request: CreateAgentProviderSessionRequest,
1499 ) -> ProviderResult<AgentSession> {
1500 Err(crate::Error::unimplemented(
1501 "agent create session is not implemented",
1502 ))
1503 }
1504
1505 async fn get_session(
1507 &self,
1508 _request: GetAgentProviderSessionRequest,
1509 ) -> ProviderResult<AgentSession> {
1510 Err(crate::Error::unimplemented(
1511 "agent get session is not implemented",
1512 ))
1513 }
1514
1515 async fn list_sessions(
1517 &self,
1518 _request: ListAgentProviderSessionsRequest,
1519 ) -> ProviderResult<ListAgentProviderSessionsResponse> {
1520 Err(crate::Error::unimplemented(
1521 "agent list sessions is not implemented",
1522 ))
1523 }
1524
1525 async fn update_session(
1527 &self,
1528 _request: UpdateAgentProviderSessionRequest,
1529 ) -> ProviderResult<AgentSession> {
1530 Err(crate::Error::unimplemented(
1531 "agent update session is not implemented",
1532 ))
1533 }
1534
1535 async fn create_turn(
1537 &self,
1538 _request: CreateAgentProviderTurnRequest,
1539 ) -> ProviderResult<AgentTurn> {
1540 Err(crate::Error::unimplemented(
1541 "agent create turn is not implemented",
1542 ))
1543 }
1544
1545 async fn get_turn(&self, _request: GetAgentProviderTurnRequest) -> ProviderResult<AgentTurn> {
1547 Err(crate::Error::unimplemented(
1548 "agent get turn is not implemented",
1549 ))
1550 }
1551
1552 async fn list_turns(
1554 &self,
1555 _request: ListAgentProviderTurnsRequest,
1556 ) -> ProviderResult<ListAgentProviderTurnsResponse> {
1557 Err(crate::Error::unimplemented(
1558 "agent list turns is not implemented",
1559 ))
1560 }
1561
1562 async fn cancel_turn(
1564 &self,
1565 _request: CancelAgentProviderTurnRequest,
1566 ) -> ProviderResult<AgentTurn> {
1567 Err(crate::Error::unimplemented(
1568 "agent cancel turn is not implemented",
1569 ))
1570 }
1571
1572 async fn list_turn_events(
1574 &self,
1575 _request: ListAgentProviderTurnEventsRequest,
1576 ) -> ProviderResult<ListAgentProviderTurnEventsResponse> {
1577 Err(crate::Error::unimplemented(
1578 "agent list turn events is not implemented",
1579 ))
1580 }
1581
1582 async fn get_interaction(
1584 &self,
1585 _request: GetAgentProviderInteractionRequest,
1586 ) -> ProviderResult<AgentInteraction> {
1587 Err(crate::Error::unimplemented(
1588 "agent get interaction is not implemented",
1589 ))
1590 }
1591
1592 async fn list_interactions(
1594 &self,
1595 _request: ListAgentProviderInteractionsRequest,
1596 ) -> ProviderResult<ListAgentProviderInteractionsResponse> {
1597 Err(crate::Error::unimplemented(
1598 "agent list interactions is not implemented",
1599 ))
1600 }
1601
1602 async fn resolve_interaction(
1604 &self,
1605 _request: ResolveAgentProviderInteractionRequest,
1606 ) -> ProviderResult<AgentInteraction> {
1607 Err(crate::Error::unimplemented(
1608 "agent resolve interaction is not implemented",
1609 ))
1610 }
1611
1612 async fn get_capabilities(
1614 &self,
1615 _request: GetAgentProviderCapabilitiesRequest,
1616 ) -> ProviderResult<AgentProviderCapabilities> {
1617 Err(crate::Error::unimplemented(
1618 "agent get capabilities is not implemented",
1619 ))
1620 }
1621}
1622
1623#[derive(Clone)]
1624pub(crate) struct AgentServer<P> {
1625 provider: Arc<P>,
1626}
1627
1628impl<P> AgentServer<P> {
1629 pub(crate) fn new(provider: Arc<P>) -> Self {
1630 Self { provider }
1631 }
1632}
1633
1634#[async_trait]
1635impl<P> pb::agent_server::Agent for AgentServer<P>
1636where
1637 P: AgentProvider,
1638{
1639 async fn create_session(
1640 &self,
1641 request: GrpcRequest<pb::CreateAgentProviderSessionRequest>,
1642 ) -> std::result::Result<GrpcResponse<pb::AgentSession>, Status> {
1643 let request = request.into_inner();
1644 let context = request.context.clone();
1645 let session = scope_request_context(
1646 context,
1647 self.provider
1648 .create_session(create_session_request_from_proto(request)),
1649 )
1650 .await
1651 .map_err(|error| rpc_status("agent create session", error))?;
1652 Ok(GrpcResponse::new(session_to_proto(session).map_err(
1653 |error| rpc_status("agent create session", error),
1654 )?))
1655 }
1656
1657 async fn get_session(
1658 &self,
1659 request: GrpcRequest<pb::GetAgentProviderSessionRequest>,
1660 ) -> std::result::Result<GrpcResponse<pb::AgentSession>, Status> {
1661 let request = request.into_inner();
1662 let context = request.context.clone();
1663 let session = scope_request_context(
1664 context,
1665 self.provider.get_session(GetAgentProviderSessionRequest {
1666 provider_name: request.provider_name,
1667 session_id: request.session_id,
1668 }),
1669 )
1670 .await
1671 .map_err(|error| rpc_status("agent get session", error))?;
1672 Ok(GrpcResponse::new(
1673 session_to_proto(session).map_err(|error| rpc_status("agent get session", error))?,
1674 ))
1675 }
1676
1677 async fn list_sessions(
1678 &self,
1679 request: GrpcRequest<pb::ListAgentProviderSessionsRequest>,
1680 ) -> std::result::Result<GrpcResponse<pb::ListAgentProviderSessionsResponse>, Status> {
1681 let request = request.into_inner();
1682 let context = request.context.clone();
1683 let response = scope_request_context(
1684 context,
1685 self.provider
1686 .list_sessions(ListAgentProviderSessionsRequest {
1687 provider_name: request.provider_name,
1688 session_ids: request.session_ids,
1689 state: AgentSessionState::from_i32_lossy(request.state),
1690 limit: request.limit,
1691 summary_only: request.summary_only,
1692 }),
1693 )
1694 .await
1695 .map_err(|error| rpc_status("agent list sessions", error))?;
1696 Ok(GrpcResponse::new(pb::ListAgentProviderSessionsResponse {
1697 sessions: response
1698 .sessions
1699 .into_iter()
1700 .map(session_to_proto)
1701 .collect::<ProviderResult<Vec<_>>>()
1702 .map_err(|error| rpc_status("agent list sessions", error))?,
1703 }))
1704 }
1705
1706 async fn update_session(
1707 &self,
1708 request: GrpcRequest<pb::UpdateAgentProviderSessionRequest>,
1709 ) -> std::result::Result<GrpcResponse<pb::AgentSession>, Status> {
1710 let request = request.into_inner();
1711 let context = request.context.clone();
1712 let session = scope_request_context(
1713 context,
1714 self.provider
1715 .update_session(UpdateAgentProviderSessionRequest {
1716 provider_name: request.provider_name,
1717 session_id: request.session_id,
1718 client_ref: request.client_ref,
1719 state: AgentSessionState::from_i32_lossy(request.state),
1720 metadata: json_from_struct(request.metadata),
1721 }),
1722 )
1723 .await
1724 .map_err(|error| rpc_status("agent update session", error))?;
1725 Ok(GrpcResponse::new(session_to_proto(session).map_err(
1726 |error| rpc_status("agent update session", error),
1727 )?))
1728 }
1729
1730 async fn create_turn(
1731 &self,
1732 request: GrpcRequest<pb::CreateAgentProviderTurnRequest>,
1733 ) -> std::result::Result<GrpcResponse<pb::AgentTurn>, Status> {
1734 let request = request.into_inner();
1735 let context = request.context.clone();
1736 let turn = scope_request_context(
1737 context,
1738 self.provider.create_turn(
1739 create_turn_request_from_proto(request)
1740 .map_err(|error| rpc_status("agent create turn", error))?,
1741 ),
1742 )
1743 .await
1744 .map_err(|error| rpc_status("agent create turn", error))?;
1745 Ok(GrpcResponse::new(
1746 turn_to_proto(turn).map_err(|error| rpc_status("agent create turn", error))?,
1747 ))
1748 }
1749
1750 async fn get_turn(
1751 &self,
1752 request: GrpcRequest<pb::GetAgentProviderTurnRequest>,
1753 ) -> std::result::Result<GrpcResponse<pb::AgentTurn>, Status> {
1754 let request = request.into_inner();
1755 let context = request.context.clone();
1756 let turn = scope_request_context(
1757 context,
1758 self.provider.get_turn(GetAgentProviderTurnRequest {
1759 provider_name: request.provider_name,
1760 turn_id: request.turn_id,
1761 }),
1762 )
1763 .await
1764 .map_err(|error| rpc_status("agent get turn", error))?;
1765 Ok(GrpcResponse::new(
1766 turn_to_proto(turn).map_err(|error| rpc_status("agent get turn", error))?,
1767 ))
1768 }
1769
1770 async fn list_turns(
1771 &self,
1772 request: GrpcRequest<pb::ListAgentProviderTurnsRequest>,
1773 ) -> std::result::Result<GrpcResponse<pb::ListAgentProviderTurnsResponse>, Status> {
1774 let request = request.into_inner();
1775 let context = request.context.clone();
1776 let response = scope_request_context(
1777 context,
1778 self.provider.list_turns(ListAgentProviderTurnsRequest {
1779 provider_name: request.provider_name,
1780 session_id: request.session_id,
1781 turn_ids: request.turn_ids,
1782 status: AgentExecutionStatus::from_i32_lossy(request.status),
1783 limit: request.limit,
1784 summary_only: request.summary_only,
1785 }),
1786 )
1787 .await
1788 .map_err(|error| rpc_status("agent list turns", error))?;
1789 Ok(GrpcResponse::new(pb::ListAgentProviderTurnsResponse {
1790 turns: response
1791 .turns
1792 .into_iter()
1793 .map(turn_to_proto)
1794 .collect::<ProviderResult<Vec<_>>>()
1795 .map_err(|error| rpc_status("agent list turns", error))?,
1796 }))
1797 }
1798
1799 async fn cancel_turn(
1800 &self,
1801 request: GrpcRequest<pb::CancelAgentProviderTurnRequest>,
1802 ) -> std::result::Result<GrpcResponse<pb::AgentTurn>, Status> {
1803 let request = request.into_inner();
1804 let context = request.context.clone();
1805 let turn = scope_request_context(
1806 context,
1807 self.provider.cancel_turn(CancelAgentProviderTurnRequest {
1808 provider_name: request.provider_name,
1809 turn_id: request.turn_id,
1810 reason: request.reason,
1811 }),
1812 )
1813 .await
1814 .map_err(|error| rpc_status("agent cancel turn", error))?;
1815 Ok(GrpcResponse::new(
1816 turn_to_proto(turn).map_err(|error| rpc_status("agent cancel turn", error))?,
1817 ))
1818 }
1819
1820 async fn list_turn_events(
1821 &self,
1822 request: GrpcRequest<pb::ListAgentProviderTurnEventsRequest>,
1823 ) -> std::result::Result<GrpcResponse<pb::ListAgentProviderTurnEventsResponse>, Status> {
1824 let request = request.into_inner();
1825 let context = request.context.clone();
1826 let response = scope_request_context(
1827 context,
1828 self.provider
1829 .list_turn_events(ListAgentProviderTurnEventsRequest {
1830 provider_name: request.provider_name,
1831 turn_id: request.turn_id,
1832 after_seq: request.after_seq,
1833 limit: request.limit,
1834 }),
1835 )
1836 .await
1837 .map_err(|error| rpc_status("agent list turn events", error))?;
1838 Ok(GrpcResponse::new(pb::ListAgentProviderTurnEventsResponse {
1839 events: response
1840 .events
1841 .into_iter()
1842 .map(event_to_proto)
1843 .collect::<ProviderResult<Vec<_>>>()
1844 .map_err(|error| rpc_status("agent list turn events", error))?,
1845 }))
1846 }
1847
1848 async fn get_interaction(
1849 &self,
1850 request: GrpcRequest<pb::GetAgentProviderInteractionRequest>,
1851 ) -> std::result::Result<GrpcResponse<pb::AgentInteraction>, Status> {
1852 let request = request.into_inner();
1853 let context = request.context.clone();
1854 let interaction = scope_request_context(
1855 context,
1856 self.provider
1857 .get_interaction(GetAgentProviderInteractionRequest {
1858 interaction_id: request.interaction_id,
1859 }),
1860 )
1861 .await
1862 .map_err(|error| rpc_status("agent get interaction", error))?;
1863 Ok(GrpcResponse::new(
1864 interaction_to_proto(interaction)
1865 .map_err(|error| rpc_status("agent get interaction", error))?,
1866 ))
1867 }
1868
1869 async fn list_interactions(
1870 &self,
1871 request: GrpcRequest<pb::ListAgentProviderInteractionsRequest>,
1872 ) -> std::result::Result<GrpcResponse<pb::ListAgentProviderInteractionsResponse>, Status> {
1873 let request = request.into_inner();
1874 let context = request.context.clone();
1875 let response = scope_request_context(
1876 context,
1877 self.provider
1878 .list_interactions(ListAgentProviderInteractionsRequest {
1879 provider_name: request.provider_name,
1880 turn_id: request.turn_id,
1881 }),
1882 )
1883 .await
1884 .map_err(|error| rpc_status("agent list interactions", error))?;
1885 Ok(GrpcResponse::new(
1886 pb::ListAgentProviderInteractionsResponse {
1887 interactions: response
1888 .interactions
1889 .into_iter()
1890 .map(interaction_to_proto)
1891 .collect::<ProviderResult<Vec<_>>>()
1892 .map_err(|error| rpc_status("agent list interactions", error))?,
1893 },
1894 ))
1895 }
1896
1897 async fn resolve_interaction(
1898 &self,
1899 request: GrpcRequest<pb::ResolveAgentProviderInteractionRequest>,
1900 ) -> std::result::Result<GrpcResponse<pb::AgentInteraction>, Status> {
1901 let request = request.into_inner();
1902 let context = request.context.clone();
1903 let interaction = scope_request_context(
1904 context,
1905 self.provider
1906 .resolve_interaction(ResolveAgentProviderInteractionRequest {
1907 provider_name: request.provider_name,
1908 interaction_id: request.interaction_id,
1909 resolution: json_from_struct(request.resolution),
1910 }),
1911 )
1912 .await
1913 .map_err(|error| rpc_status("agent resolve interaction", error))?;
1914 Ok(GrpcResponse::new(
1915 interaction_to_proto(interaction)
1916 .map_err(|error| rpc_status("agent resolve interaction", error))?,
1917 ))
1918 }
1919
1920 async fn get_capabilities(
1921 &self,
1922 _request: GrpcRequest<pb::GetAgentProviderCapabilitiesRequest>,
1923 ) -> std::result::Result<GrpcResponse<pb::AgentProviderCapabilities>, Status> {
1924 let capabilities = self
1925 .provider
1926 .get_capabilities(GetAgentProviderCapabilitiesRequest {})
1927 .await
1928 .map_err(|error| rpc_status("agent get capabilities", error))?;
1929 Ok(GrpcResponse::new(capabilities_to_proto(capabilities)))
1930 }
1931}