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 created_by_subject_id: Option<String>,
605 pub subject: Option<Subject>,
607 pub session_start: Option<AgentSessionStartConfig>,
609 pub prepared_workspace: Option<AgentPreparedWorkspace>,
611 pub tools: Option<AgentToolConfig>,
613}
614
615#[derive(Debug, Clone, Default, PartialEq, Eq)]
616pub struct AgentSessionStartConfig {
618 pub hooks: Vec<AgentSessionStartHook>,
620}
621
622#[derive(Debug, Clone, Default, PartialEq, Eq)]
623pub struct AgentSessionStartHook {
625 pub id: String,
627 pub r#type: String,
629 pub command: Vec<String>,
631 pub cwd: String,
633 pub timeout: String,
635 pub env: std::collections::HashMap<String, String>,
637 pub output: Option<AgentSessionStartHookOutput>,
639}
640
641#[derive(Debug, Clone, Default, PartialEq, Eq)]
642pub struct AgentSessionStartHookOutput {
644 pub additional_context: bool,
646 pub metadata: bool,
648}
649
650#[derive(Debug, Clone, Default, PartialEq, Eq)]
651pub struct GetAgentProviderSessionRequest {
653 pub provider_name: String,
655 pub session_id: String,
657 pub subject: Option<Subject>,
659}
660
661#[derive(Debug, Clone, Default, PartialEq, Eq)]
662pub struct ListAgentProviderSessionsRequest {
664 pub provider_name: String,
666 pub subject: Option<Subject>,
668 pub session_ids: Vec<String>,
670 pub state: AgentSessionState,
672 pub limit: i32,
674 pub summary_only: bool,
676}
677
678#[derive(Debug, Clone, Default, PartialEq)]
679pub struct ListAgentProviderSessionsResponse {
681 pub sessions: Vec<AgentSession>,
683}
684
685#[derive(Debug, Clone, Default, PartialEq)]
686pub struct UpdateAgentProviderSessionRequest {
688 pub provider_name: String,
690 pub session_id: String,
692 pub client_ref: String,
694 pub state: AgentSessionState,
696 pub metadata: Option<AgentJson>,
698 pub subject: Option<Subject>,
700}
701
702#[derive(Debug, Clone, Default, PartialEq)]
703pub struct AgentTurn {
705 pub id: String,
707 pub session_id: String,
709 pub provider_name: String,
711 pub model: String,
713 pub status: AgentExecutionStatus,
715 pub messages: Vec<AgentMessage>,
717 pub output: Option<AgentTurnOutput>,
719 pub status_message: String,
721 pub created_by_subject_id: Option<String>,
723 pub created_at: Option<SystemTime>,
725 pub started_at: Option<SystemTime>,
727 pub completed_at: Option<SystemTime>,
729 pub execution_ref: String,
731}
732
733#[derive(Debug, Clone, PartialEq)]
734pub enum AgentTurnOutput {
736 Text(AgentTurnTextOutput),
738 Structured(AgentTurnStructuredOutput),
740}
741
742#[derive(Debug, Clone, Default, PartialEq, Eq)]
743pub struct AgentTurnTextOutput {
745 pub text: String,
747}
748
749#[derive(Debug, Clone, Default, PartialEq)]
750pub struct AgentTurnStructuredOutput {
752 pub text: String,
754 pub value: Option<AgentJson>,
756}
757
758#[derive(Debug, Clone, Default, PartialEq)]
759pub struct AgentTurnDisplay {
761 pub kind: String,
763 pub phase: String,
765 pub text: String,
767 pub label: String,
769 pub r#ref: String,
771 pub parent_ref: String,
773 pub input: Option<AgentJson>,
775 pub output: Option<AgentJson>,
777 pub error: Option<AgentJson>,
779 pub action: String,
781 pub format: String,
783 pub language: String,
785}
786
787#[derive(Debug, Clone, PartialEq)]
788pub struct CreateAgentProviderTurnRequest {
790 pub provider_name: String,
792 pub turn_id: String,
794 pub session_id: String,
796 pub idempotency_key: String,
798 pub model: String,
800 pub messages: Vec<AgentMessage>,
802 pub output: AgentOutput,
804 pub metadata: Option<AgentJson>,
806 pub created_by_subject_id: Option<String>,
808 pub execution_ref: String,
810 pub subject: Option<Subject>,
812 pub model_options: Option<AgentJson>,
814 pub timeout_seconds: i32,
816 pub context: Option<pb::RequestContext>,
818}
819
820#[derive(Debug, Clone, PartialEq)]
821pub enum AgentOutput {
823 Text(AgentTextOutput),
825 Structured(AgentStructuredOutput),
827}
828
829#[derive(Debug, Clone, Default, PartialEq, Eq)]
830pub struct AgentTextOutput {}
832
833#[derive(Debug, Clone, PartialEq)]
834pub struct AgentStructuredOutput {
836 pub schema: AgentJson,
838}
839
840impl AgentOutput {
841 pub fn text() -> Self {
843 Self::Text(AgentTextOutput {})
844 }
845
846 pub fn structured_schema<T: Serialize>(schema: T) -> ProviderResult<Self> {
848 Ok(Self::Structured(AgentStructuredOutput {
849 schema: protocol::json_from_serializable(schema)?,
850 }))
851 }
852}
853
854#[derive(Debug, Clone, Default, PartialEq, Eq)]
855pub struct GetAgentProviderTurnRequest {
857 pub provider_name: String,
859 pub turn_id: String,
861 pub subject: Option<Subject>,
863}
864
865#[derive(Debug, Clone, Default, PartialEq, Eq)]
866pub struct ListAgentProviderTurnsRequest {
868 pub provider_name: String,
870 pub session_id: String,
872 pub subject: Option<Subject>,
874 pub turn_ids: Vec<String>,
876 pub status: AgentExecutionStatus,
878 pub limit: i32,
880 pub summary_only: bool,
882}
883
884#[derive(Debug, Clone, Default, PartialEq)]
885pub struct ListAgentProviderTurnsResponse {
887 pub turns: Vec<AgentTurn>,
889}
890
891#[derive(Debug, Clone, Default, PartialEq, Eq)]
892pub struct CancelAgentProviderTurnRequest {
894 pub provider_name: String,
896 pub turn_id: String,
898 pub reason: String,
900 pub subject: Option<Subject>,
902}
903
904#[derive(Debug, Clone, Default, PartialEq)]
905pub struct AgentTurnEvent {
907 pub id: String,
909 pub turn_id: String,
911 pub seq: i64,
913 pub r#type: String,
915 pub source: String,
917 pub visibility: String,
919 pub data: Option<AgentJson>,
921 pub created_at: Option<SystemTime>,
923 pub display: Option<AgentTurnDisplay>,
925}
926
927#[derive(Debug, Clone, Default, PartialEq, Eq)]
928pub struct ListAgentProviderTurnEventsRequest {
930 pub provider_name: String,
932 pub turn_id: String,
934 pub after_seq: i64,
936 pub limit: i32,
938 pub subject: Option<Subject>,
940}
941
942#[derive(Debug, Clone, Default, PartialEq)]
943pub struct ListAgentProviderTurnEventsResponse {
945 pub events: Vec<AgentTurnEvent>,
947}
948
949#[derive(Debug, Clone, Default, PartialEq, Eq)]
950pub struct GetAgentProviderInteractionRequest {
952 pub interaction_id: String,
954 pub subject: Option<Subject>,
956}
957
958#[derive(Debug, Clone, Default, PartialEq, Eq)]
959pub struct ListAgentProviderInteractionsRequest {
961 pub provider_name: String,
963 pub turn_id: String,
965 pub subject: Option<Subject>,
967}
968
969#[derive(Debug, Clone, Default, PartialEq)]
970pub struct ListAgentProviderInteractionsResponse {
972 pub interactions: Vec<AgentInteraction>,
974}
975
976#[derive(Debug, Clone, Default, PartialEq)]
977pub struct ResolveAgentProviderInteractionRequest {
979 pub provider_name: String,
981 pub interaction_id: String,
983 pub resolution: Option<AgentJson>,
985 pub subject: Option<Subject>,
987}
988
989#[derive(Debug, Clone, Default, PartialEq, Eq)]
990pub struct AgentToolAnnotations {
992 pub read_only_hint: Option<bool>,
994 pub idempotent_hint: Option<bool>,
996 pub destructive_hint: Option<bool>,
998 pub open_world_hint: Option<bool>,
1000}
1001
1002#[derive(Debug, Clone, Default, PartialEq)]
1003pub struct ListedAgentTool {
1005 pub id: String,
1007 pub mcp_name: String,
1009 pub title: String,
1011 pub description: String,
1013 pub input_schema: String,
1015 pub output_schema: String,
1017 pub annotations: Option<AgentToolAnnotations>,
1019 pub r#ref: Option<AgentToolRef>,
1021 pub tags: Vec<String>,
1023 pub search_text: String,
1025}
1026
1027pub fn new_agent_message(input: AgentMessage) -> ProviderResult<AgentMessage> {
1029 Ok(AgentMessage {
1030 role: input.role,
1031 text: input.text,
1032 parts: input
1033 .parts
1034 .into_iter()
1035 .map(new_agent_message_part)
1036 .collect::<ProviderResult<Vec<_>>>()?,
1037 metadata: input.metadata,
1038 })
1039}
1040
1041pub fn new_agent_message_part(input: AgentMessagePart) -> ProviderResult<AgentMessagePart> {
1043 let mut part_type = input.r#type;
1044 if part_type == AgentMessagePartType::Unspecified {
1045 part_type = infer_agent_message_part_type(&input);
1046 }
1047 Ok(AgentMessagePart {
1048 r#type: part_type,
1049 text: input.text,
1050 json: input.json,
1051 tool_call: input.tool_call.map(new_agent_tool_call).transpose()?,
1052 tool_result: input.tool_result.map(new_agent_tool_result).transpose()?,
1053 image_ref: input.image_ref.map(new_agent_image_ref),
1054 })
1055}
1056
1057pub fn new_agent_tool_call(
1059 input: AgentMessagePartToolCall,
1060) -> ProviderResult<AgentMessagePartToolCall> {
1061 Ok(AgentMessagePartToolCall {
1062 id: input.id,
1063 tool_id: input.tool_id,
1064 arguments: input.arguments,
1065 })
1066}
1067
1068pub fn new_agent_tool_result(
1070 input: AgentMessagePartToolResult,
1071) -> ProviderResult<AgentMessagePartToolResult> {
1072 Ok(AgentMessagePartToolResult {
1073 tool_call_id: input.tool_call_id,
1074 status: input.status,
1075 content: input.content,
1076 output: input.output,
1077 })
1078}
1079
1080pub fn new_agent_image_ref(input: AgentMessagePartImageRef) -> AgentMessagePartImageRef {
1082 AgentMessagePartImageRef {
1083 uri: input.uri,
1084 mime_type: input.mime_type,
1085 }
1086}
1087
1088pub fn new_agent_tool_ref(input: AgentToolRef) -> AgentToolRef {
1090 AgentToolRef {
1091 app: input.app,
1092 operation: input.operation,
1093 connection: input.connection,
1094 instance: input.instance,
1095 title: input.title,
1096 description: input.description,
1097 credential_mode: input.credential_mode,
1098 system: input.system,
1099 run_as: input.run_as,
1100 }
1101}
1102
1103fn infer_agent_message_part_type(input: &AgentMessagePart) -> AgentMessagePartType {
1104 if input.tool_call.is_some() {
1105 AgentMessagePartType::ToolCall
1106 } else if input.tool_result.is_some() {
1107 AgentMessagePartType::ToolResult
1108 } else if input.image_ref.is_some() {
1109 AgentMessagePartType::ImageRef
1110 } else if input.json.is_some() {
1111 AgentMessagePartType::Json
1112 } else if !input.text.is_empty() {
1113 AgentMessagePartType::Text
1114 } else {
1115 AgentMessagePartType::Unspecified
1116 }
1117}
1118
1119fn json_from_struct(value: Option<Struct>) -> Option<AgentJson> {
1120 value.map(|value| protocol::json_from_struct(&value))
1121}
1122
1123fn struct_from_json(value: Option<AgentJson>) -> ProviderResult<Option<Struct>> {
1124 value.map(protocol::struct_from_json).transpose()
1125}
1126
1127fn value_from_json(value: Option<AgentJson>) -> Option<Value> {
1128 value.map(protocol::value_from_json)
1129}
1130
1131fn timestamp_from_time(value: Option<SystemTime>) -> Option<Timestamp> {
1132 value.map(protocol::timestamp_from_system_time)
1133}
1134
1135fn agent_subject_from_proto(value: Option<pb::SubjectContext>) -> Option<Subject> {
1136 value.map(|value| Subject {
1137 id: value.id,
1138 credential_subject_id: value.credential_subject_id,
1139 email: value.email,
1140 display_name: value.display_name,
1141 })
1142}
1143
1144pub(crate) fn agent_tool_ref_from_proto(value: pb::AgentToolRef) -> AgentToolRef {
1145 AgentToolRef {
1146 app: value.app,
1147 operation: value.operation,
1148 connection: value.connection,
1149 instance: value.instance,
1150 title: value.title,
1151 description: value.description,
1152 credential_mode: value.credential_mode,
1153 system: value.system,
1154 run_as: agent_run_as_context_from_proto(value.run_as),
1155 }
1156}
1157
1158fn agent_run_as_context_from_proto(value: Option<pb::SubjectContext>) -> Option<Subject> {
1159 value.map(|value| Subject {
1160 id: value.id,
1161 credential_subject_id: value.credential_subject_id,
1162 email: value.email,
1163 display_name: value.display_name,
1164 })
1165}
1166
1167pub(crate) fn message_from_proto(value: pb::AgentMessage) -> AgentMessage {
1168 AgentMessage {
1169 role: value.role,
1170 text: value.text,
1171 parts: value
1172 .parts
1173 .into_iter()
1174 .map(message_part_from_proto)
1175 .collect(),
1176 metadata: json_from_struct(value.metadata),
1177 }
1178}
1179
1180pub(crate) fn message_to_proto(value: AgentMessage) -> ProviderResult<pb::AgentMessage> {
1181 Ok(pb::AgentMessage {
1182 role: value.role,
1183 text: value.text,
1184 parts: value
1185 .parts
1186 .into_iter()
1187 .map(message_part_to_proto)
1188 .collect::<ProviderResult<Vec<_>>>()?,
1189 metadata: struct_from_json(value.metadata)?,
1190 })
1191}
1192
1193fn message_part_from_proto(value: pb::AgentMessagePart) -> AgentMessagePart {
1194 AgentMessagePart {
1195 r#type: AgentMessagePartType::from_i32_lossy(value.r#type),
1196 text: value.text,
1197 json: json_from_struct(value.json),
1198 tool_call: value.tool_call.map(|value| AgentMessagePartToolCall {
1199 id: value.id,
1200 tool_id: value.tool_id,
1201 arguments: json_from_struct(value.arguments),
1202 }),
1203 tool_result: value.tool_result.map(|value| AgentMessagePartToolResult {
1204 tool_call_id: value.tool_call_id,
1205 status: value.status,
1206 content: value.content,
1207 output: json_from_struct(value.output),
1208 }),
1209 image_ref: value.image_ref.map(|value| AgentMessagePartImageRef {
1210 uri: value.uri,
1211 mime_type: value.mime_type,
1212 }),
1213 }
1214}
1215
1216fn message_part_to_proto(value: AgentMessagePart) -> ProviderResult<pb::AgentMessagePart> {
1217 Ok(pb::AgentMessagePart {
1218 r#type: value.r#type.as_i32(),
1219 text: value.text,
1220 json: struct_from_json(value.json)?,
1221 tool_call: value
1222 .tool_call
1223 .map(|value| -> ProviderResult<pb::AgentMessagePartToolCall> {
1224 Ok(pb::AgentMessagePartToolCall {
1225 id: value.id,
1226 tool_id: value.tool_id,
1227 arguments: struct_from_json(value.arguments)?,
1228 })
1229 })
1230 .transpose()?,
1231 tool_result: value
1232 .tool_result
1233 .map(|value| -> ProviderResult<pb::AgentMessagePartToolResult> {
1234 Ok(pb::AgentMessagePartToolResult {
1235 tool_call_id: value.tool_call_id,
1236 status: value.status,
1237 content: value.content,
1238 output: struct_from_json(value.output)?,
1239 })
1240 })
1241 .transpose()?,
1242 image_ref: value.image_ref.map(|value| pb::AgentMessagePartImageRef {
1243 uri: value.uri,
1244 mime_type: value.mime_type,
1245 }),
1246 })
1247}
1248
1249fn session_to_proto(value: AgentSession) -> ProviderResult<pb::AgentSession> {
1250 Ok(pb::AgentSession {
1251 id: value.id,
1252 provider_name: value.provider_name,
1253 model: value.model,
1254 client_ref: value.client_ref,
1255 state: value.state.as_i32(),
1256 metadata: struct_from_json(value.metadata)?,
1257 created_by_subject_id: value.created_by_subject_id.clone().unwrap_or_default(),
1258 created_at: timestamp_from_time(value.created_at),
1259 updated_at: timestamp_from_time(value.updated_at),
1260 last_turn_at: timestamp_from_time(value.last_turn_at),
1261 })
1262}
1263
1264fn turn_to_proto(value: AgentTurn) -> ProviderResult<pb::AgentTurn> {
1265 Ok(pb::AgentTurn {
1266 id: value.id,
1267 session_id: value.session_id,
1268 provider_name: value.provider_name,
1269 model: value.model,
1270 status: value.status.as_i32(),
1271 messages: value
1272 .messages
1273 .into_iter()
1274 .map(message_to_proto)
1275 .collect::<ProviderResult<Vec<_>>>()?,
1276 output: agent_turn_output_to_proto(value.output)?,
1277 status_message: value.status_message,
1278 created_by_subject_id: value.created_by_subject_id.clone().unwrap_or_default(),
1279 created_at: timestamp_from_time(value.created_at),
1280 started_at: timestamp_from_time(value.started_at),
1281 completed_at: timestamp_from_time(value.completed_at),
1282 execution_ref: value.execution_ref,
1283 })
1284}
1285
1286fn display_to_proto(value: AgentTurnDisplay) -> pb::AgentTurnDisplay {
1287 pb::AgentTurnDisplay {
1288 kind: value.kind,
1289 phase: value.phase,
1290 text: value.text,
1291 label: value.label,
1292 r#ref: value.r#ref,
1293 parent_ref: value.parent_ref,
1294 input: value_from_json(value.input),
1295 output: value_from_json(value.output),
1296 error: value_from_json(value.error),
1297 action: value.action,
1298 format: value.format,
1299 language: value.language,
1300 }
1301}
1302
1303fn agent_turn_output_to_proto(
1304 value: Option<AgentTurnOutput>,
1305) -> ProviderResult<Option<pb::agent_turn::Output>> {
1306 match value {
1307 Some(AgentTurnOutput::Text(output)) => Ok(Some(pb::agent_turn::Output::Text(
1308 pb::AgentTurnTextOutput { text: output.text },
1309 ))),
1310 Some(AgentTurnOutput::Structured(output)) => Ok(Some(pb::agent_turn::Output::Structured(
1311 pb::AgentTurnStructuredOutput {
1312 text: output.text,
1313 value: struct_from_json(output.value)?,
1314 },
1315 ))),
1316 None => Ok(None),
1317 }
1318}
1319
1320fn agent_output_from_proto(value: Option<pb::AgentOutput>) -> ProviderResult<Option<AgentOutput>> {
1321 match value.and_then(|output| output.kind) {
1322 Some(pb::agent_output::Kind::Text(_)) => Ok(Some(AgentOutput::Text(AgentTextOutput {}))),
1323 Some(pb::agent_output::Kind::Structured(output)) => {
1324 let schema = json_from_struct(output.schema)
1325 .ok_or_else(|| crate::Error::bad_request("output.structured.schema is required"))?;
1326 Ok(Some(AgentOutput::Structured(AgentStructuredOutput {
1327 schema,
1328 })))
1329 }
1330 None => Ok(None),
1331 }
1332}
1333
1334fn required_agent_output_from_proto(value: Option<pb::AgentOutput>) -> ProviderResult<AgentOutput> {
1335 agent_output_from_proto(value)?
1336 .ok_or_else(|| crate::Error::bad_request("create turn output is required"))
1337}
1338
1339fn event_to_proto(value: AgentTurnEvent) -> ProviderResult<pb::AgentTurnEvent> {
1340 Ok(pb::AgentTurnEvent {
1341 id: value.id,
1342 turn_id: value.turn_id,
1343 seq: value.seq,
1344 r#type: value.r#type,
1345 source: value.source,
1346 visibility: value.visibility,
1347 data: struct_from_json(value.data)?,
1348 created_at: timestamp_from_time(value.created_at),
1349 display: value.display.map(display_to_proto),
1350 })
1351}
1352
1353fn interaction_to_proto(value: AgentInteraction) -> ProviderResult<pb::AgentInteraction> {
1354 Ok(pb::AgentInteraction {
1355 id: value.id,
1356 r#type: value.r#type.as_i32(),
1357 state: value.state.as_i32(),
1358 title: value.title,
1359 prompt: value.prompt,
1360 request: struct_from_json(value.request)?,
1361 resolution: struct_from_json(value.resolution)?,
1362 created_at: timestamp_from_time(value.created_at),
1363 resolved_at: timestamp_from_time(value.resolved_at),
1364 turn_id: value.turn_id,
1365 session_id: value.session_id,
1366 })
1367}
1368
1369fn capabilities_to_proto(value: AgentProviderCapabilities) -> pb::AgentProviderCapabilities {
1370 pb::AgentProviderCapabilities {
1371 streaming_text: value.streaming_text,
1372 tool_calls: value.tool_calls,
1373 parallel_tool_calls: value.parallel_tool_calls,
1374 interactions: value.interactions,
1375 resumable_turns: value.resumable_turns,
1376 reasoning_summaries: value.reasoning_summaries,
1377 bounded_list_hydration: value.bounded_list_hydration,
1378 supported_tool_sources: value
1379 .supported_tool_sources
1380 .into_iter()
1381 .map(AgentToolSourceMode::as_i32)
1382 .collect(),
1383 supports_session_start: value.supports_session_start,
1384 supports_prepared_workspace: value.supports_prepared_workspace,
1385 }
1386}
1387
1388fn create_session_request_from_proto(
1389 value: pb::CreateAgentProviderSessionRequest,
1390) -> CreateAgentProviderSessionRequest {
1391 CreateAgentProviderSessionRequest {
1392 idempotency_key: value.idempotency_key,
1393 model: value.model,
1394 client_ref: value.client_ref,
1395 metadata: json_from_struct(value.metadata),
1396 created_by_subject_id: Some(value.created_by_subject_id)
1397 .filter(|value| !value.trim().is_empty())
1398 .map(|value| value.to_string()),
1399 subject: agent_subject_from_proto(value.subject),
1400 session_start: value.session_start.map(|value| AgentSessionStartConfig {
1401 hooks: value
1402 .hooks
1403 .into_iter()
1404 .map(|hook| AgentSessionStartHook {
1405 id: hook.id,
1406 r#type: hook.r#type,
1407 command: hook.command,
1408 cwd: hook.cwd,
1409 timeout: hook.timeout,
1410 env: hook.env.into_iter().collect(),
1411 output: hook.output.map(|output| AgentSessionStartHookOutput {
1412 additional_context: output.additional_context,
1413 metadata: output.metadata,
1414 }),
1415 })
1416 .collect(),
1417 }),
1418 prepared_workspace: value
1419 .prepared_workspace
1420 .map(|value| AgentPreparedWorkspace {
1421 root: value.root,
1422 cwd: value.cwd,
1423 }),
1424 tools: value.tools.map(agent_tool_config_from_proto),
1425 }
1426}
1427
1428fn create_turn_request_from_proto(
1429 value: pb::CreateAgentProviderTurnRequest,
1430) -> ProviderResult<CreateAgentProviderTurnRequest> {
1431 if value.timeout_seconds < 0 {
1432 return Err(crate::Error::bad_request(
1433 "agent create turn timeout_seconds must not be negative",
1434 ));
1435 }
1436 Ok(CreateAgentProviderTurnRequest {
1437 provider_name: value.provider_name,
1438 turn_id: value.turn_id,
1439 session_id: value.session_id,
1440 idempotency_key: value.idempotency_key,
1441 model: value.model,
1442 messages: value.messages.into_iter().map(message_from_proto).collect(),
1443 output: required_agent_output_from_proto(value.output)?,
1444 metadata: json_from_struct(value.metadata),
1445 created_by_subject_id: Some(value.created_by_subject_id)
1446 .filter(|value| !value.trim().is_empty())
1447 .map(|value| value.to_string()),
1448 execution_ref: value.execution_ref,
1449 subject: agent_subject_from_proto(value.subject),
1450 model_options: json_from_struct(value.model_options),
1451 timeout_seconds: value.timeout_seconds,
1452 context: value.context,
1453 })
1454}
1455
1456fn listed_tool_from_proto(value: pb::ListedAgentTool) -> ListedAgentTool {
1457 ListedAgentTool {
1458 id: value.id,
1459 mcp_name: value.mcp_name,
1460 title: value.title,
1461 description: value.description,
1462 input_schema: value.input_schema,
1463 output_schema: value.output_schema,
1464 annotations: value.annotations.map(|annotations| AgentToolAnnotations {
1465 read_only_hint: annotations.read_only_hint,
1466 idempotent_hint: annotations.idempotent_hint,
1467 destructive_hint: annotations.destructive_hint,
1468 open_world_hint: annotations.open_world_hint,
1469 }),
1470 r#ref: value.r#ref.map(agent_tool_ref_from_proto),
1471 tags: value.tags,
1472 search_text: value.search_text,
1473 }
1474}
1475
1476fn agent_tool_config_from_proto(value: pb::AgentToolConfig) -> AgentToolConfig {
1477 let source = match value.source {
1478 Some(pb::agent_tool_config::Source::None(_)) => {
1479 Some(AgentToolConfigSource::None(AgentNoTools {}))
1480 }
1481 Some(pb::agent_tool_config::Source::Catalog(catalog)) => {
1482 Some(AgentToolConfigSource::Catalog(AgentCatalogToolConfig {
1483 refs: catalog
1484 .refs
1485 .into_iter()
1486 .map(agent_tool_ref_from_proto)
1487 .collect(),
1488 tools: catalog
1489 .tools
1490 .into_iter()
1491 .map(listed_tool_from_proto)
1492 .collect(),
1493 }))
1494 }
1495 None => None,
1496 };
1497 AgentToolConfig { source }
1498}
1499
1500#[async_trait]
1501pub trait AgentProvider: Send + Sync + 'static {
1503 async fn configure(
1505 &self,
1506 _name: &str,
1507 _config: serde_json::Map<String, serde_json::Value>,
1508 ) -> ProviderResult<()> {
1509 Ok(())
1510 }
1511
1512 fn metadata(&self) -> Option<RuntimeMetadata> {
1514 None
1515 }
1516
1517 fn warnings(&self) -> Vec<String> {
1519 Vec::new()
1520 }
1521
1522 async fn health_check(&self) -> ProviderResult<()> {
1524 Ok(())
1525 }
1526
1527 async fn start(&self) -> ProviderResult<()> {
1529 Ok(())
1530 }
1531
1532 async fn close(&self) -> ProviderResult<()> {
1534 Ok(())
1535 }
1536
1537 async fn create_session(
1543 &self,
1544 _request: CreateAgentProviderSessionRequest,
1545 ) -> ProviderResult<AgentSession> {
1546 Err(crate::Error::unimplemented(
1547 "agent create session is not implemented",
1548 ))
1549 }
1550
1551 async fn get_session(
1553 &self,
1554 _request: GetAgentProviderSessionRequest,
1555 ) -> ProviderResult<AgentSession> {
1556 Err(crate::Error::unimplemented(
1557 "agent get session is not implemented",
1558 ))
1559 }
1560
1561 async fn list_sessions(
1563 &self,
1564 _request: ListAgentProviderSessionsRequest,
1565 ) -> ProviderResult<ListAgentProviderSessionsResponse> {
1566 Err(crate::Error::unimplemented(
1567 "agent list sessions is not implemented",
1568 ))
1569 }
1570
1571 async fn update_session(
1573 &self,
1574 _request: UpdateAgentProviderSessionRequest,
1575 ) -> ProviderResult<AgentSession> {
1576 Err(crate::Error::unimplemented(
1577 "agent update session is not implemented",
1578 ))
1579 }
1580
1581 async fn create_turn(
1583 &self,
1584 _request: CreateAgentProviderTurnRequest,
1585 ) -> ProviderResult<AgentTurn> {
1586 Err(crate::Error::unimplemented(
1587 "agent create turn is not implemented",
1588 ))
1589 }
1590
1591 async fn get_turn(&self, _request: GetAgentProviderTurnRequest) -> ProviderResult<AgentTurn> {
1593 Err(crate::Error::unimplemented(
1594 "agent get turn is not implemented",
1595 ))
1596 }
1597
1598 async fn list_turns(
1600 &self,
1601 _request: ListAgentProviderTurnsRequest,
1602 ) -> ProviderResult<ListAgentProviderTurnsResponse> {
1603 Err(crate::Error::unimplemented(
1604 "agent list turns is not implemented",
1605 ))
1606 }
1607
1608 async fn cancel_turn(
1610 &self,
1611 _request: CancelAgentProviderTurnRequest,
1612 ) -> ProviderResult<AgentTurn> {
1613 Err(crate::Error::unimplemented(
1614 "agent cancel turn is not implemented",
1615 ))
1616 }
1617
1618 async fn list_turn_events(
1620 &self,
1621 _request: ListAgentProviderTurnEventsRequest,
1622 ) -> ProviderResult<ListAgentProviderTurnEventsResponse> {
1623 Err(crate::Error::unimplemented(
1624 "agent list turn events is not implemented",
1625 ))
1626 }
1627
1628 async fn get_interaction(
1630 &self,
1631 _request: GetAgentProviderInteractionRequest,
1632 ) -> ProviderResult<AgentInteraction> {
1633 Err(crate::Error::unimplemented(
1634 "agent get interaction is not implemented",
1635 ))
1636 }
1637
1638 async fn list_interactions(
1640 &self,
1641 _request: ListAgentProviderInteractionsRequest,
1642 ) -> ProviderResult<ListAgentProviderInteractionsResponse> {
1643 Err(crate::Error::unimplemented(
1644 "agent list interactions is not implemented",
1645 ))
1646 }
1647
1648 async fn resolve_interaction(
1650 &self,
1651 _request: ResolveAgentProviderInteractionRequest,
1652 ) -> ProviderResult<AgentInteraction> {
1653 Err(crate::Error::unimplemented(
1654 "agent resolve interaction is not implemented",
1655 ))
1656 }
1657
1658 async fn get_capabilities(
1660 &self,
1661 _request: GetAgentProviderCapabilitiesRequest,
1662 ) -> ProviderResult<AgentProviderCapabilities> {
1663 Err(crate::Error::unimplemented(
1664 "agent get capabilities is not implemented",
1665 ))
1666 }
1667}
1668
1669#[derive(Clone)]
1670pub(crate) struct AgentServer<P> {
1671 provider: Arc<P>,
1672}
1673
1674impl<P> AgentServer<P> {
1675 pub(crate) fn new(provider: Arc<P>) -> Self {
1676 Self { provider }
1677 }
1678}
1679
1680#[async_trait]
1681impl<P> pb::agent_server::Agent for AgentServer<P>
1682where
1683 P: AgentProvider,
1684{
1685 async fn create_session(
1686 &self,
1687 request: GrpcRequest<pb::CreateAgentProviderSessionRequest>,
1688 ) -> std::result::Result<GrpcResponse<pb::AgentSession>, Status> {
1689 let request = request.into_inner();
1690 let context = request.context.clone();
1691 let session = scope_request_context(
1692 context,
1693 self.provider
1694 .create_session(create_session_request_from_proto(request)),
1695 )
1696 .await
1697 .map_err(|error| rpc_status("agent create session", error))?;
1698 Ok(GrpcResponse::new(session_to_proto(session).map_err(
1699 |error| rpc_status("agent create session", error),
1700 )?))
1701 }
1702
1703 async fn get_session(
1704 &self,
1705 request: GrpcRequest<pb::GetAgentProviderSessionRequest>,
1706 ) -> std::result::Result<GrpcResponse<pb::AgentSession>, Status> {
1707 let request = request.into_inner();
1708 let context = request.context.clone();
1709 let session = scope_request_context(
1710 context,
1711 self.provider.get_session(GetAgentProviderSessionRequest {
1712 provider_name: request.provider_name,
1713 session_id: request.session_id,
1714 subject: agent_subject_from_proto(request.subject),
1715 }),
1716 )
1717 .await
1718 .map_err(|error| rpc_status("agent get session", error))?;
1719 Ok(GrpcResponse::new(
1720 session_to_proto(session).map_err(|error| rpc_status("agent get session", error))?,
1721 ))
1722 }
1723
1724 async fn list_sessions(
1725 &self,
1726 request: GrpcRequest<pb::ListAgentProviderSessionsRequest>,
1727 ) -> std::result::Result<GrpcResponse<pb::ListAgentProviderSessionsResponse>, Status> {
1728 let request = request.into_inner();
1729 let context = request.context.clone();
1730 let response = scope_request_context(
1731 context,
1732 self.provider
1733 .list_sessions(ListAgentProviderSessionsRequest {
1734 provider_name: request.provider_name,
1735 subject: agent_subject_from_proto(request.subject),
1736 session_ids: request.session_ids,
1737 state: AgentSessionState::from_i32_lossy(request.state),
1738 limit: request.limit,
1739 summary_only: request.summary_only,
1740 }),
1741 )
1742 .await
1743 .map_err(|error| rpc_status("agent list sessions", error))?;
1744 Ok(GrpcResponse::new(pb::ListAgentProviderSessionsResponse {
1745 sessions: response
1746 .sessions
1747 .into_iter()
1748 .map(session_to_proto)
1749 .collect::<ProviderResult<Vec<_>>>()
1750 .map_err(|error| rpc_status("agent list sessions", error))?,
1751 }))
1752 }
1753
1754 async fn update_session(
1755 &self,
1756 request: GrpcRequest<pb::UpdateAgentProviderSessionRequest>,
1757 ) -> std::result::Result<GrpcResponse<pb::AgentSession>, Status> {
1758 let request = request.into_inner();
1759 let context = request.context.clone();
1760 let session = scope_request_context(
1761 context,
1762 self.provider
1763 .update_session(UpdateAgentProviderSessionRequest {
1764 provider_name: request.provider_name,
1765 session_id: request.session_id,
1766 client_ref: request.client_ref,
1767 state: AgentSessionState::from_i32_lossy(request.state),
1768 metadata: json_from_struct(request.metadata),
1769 subject: agent_subject_from_proto(request.subject),
1770 }),
1771 )
1772 .await
1773 .map_err(|error| rpc_status("agent update session", error))?;
1774 Ok(GrpcResponse::new(session_to_proto(session).map_err(
1775 |error| rpc_status("agent update session", error),
1776 )?))
1777 }
1778
1779 async fn create_turn(
1780 &self,
1781 request: GrpcRequest<pb::CreateAgentProviderTurnRequest>,
1782 ) -> std::result::Result<GrpcResponse<pb::AgentTurn>, Status> {
1783 let request = request.into_inner();
1784 let context = request.context.clone();
1785 let turn = scope_request_context(
1786 context,
1787 self.provider.create_turn(
1788 create_turn_request_from_proto(request)
1789 .map_err(|error| rpc_status("agent create turn", error))?,
1790 ),
1791 )
1792 .await
1793 .map_err(|error| rpc_status("agent create turn", error))?;
1794 Ok(GrpcResponse::new(
1795 turn_to_proto(turn).map_err(|error| rpc_status("agent create turn", error))?,
1796 ))
1797 }
1798
1799 async fn get_turn(
1800 &self,
1801 request: GrpcRequest<pb::GetAgentProviderTurnRequest>,
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.get_turn(GetAgentProviderTurnRequest {
1808 provider_name: request.provider_name,
1809 turn_id: request.turn_id,
1810 subject: agent_subject_from_proto(request.subject),
1811 }),
1812 )
1813 .await
1814 .map_err(|error| rpc_status("agent get turn", error))?;
1815 Ok(GrpcResponse::new(
1816 turn_to_proto(turn).map_err(|error| rpc_status("agent get turn", error))?,
1817 ))
1818 }
1819
1820 async fn list_turns(
1821 &self,
1822 request: GrpcRequest<pb::ListAgentProviderTurnsRequest>,
1823 ) -> std::result::Result<GrpcResponse<pb::ListAgentProviderTurnsResponse>, Status> {
1824 let request = request.into_inner();
1825 let context = request.context.clone();
1826 let response = scope_request_context(
1827 context,
1828 self.provider.list_turns(ListAgentProviderTurnsRequest {
1829 provider_name: request.provider_name,
1830 session_id: request.session_id,
1831 subject: agent_subject_from_proto(request.subject),
1832 turn_ids: request.turn_ids,
1833 status: AgentExecutionStatus::from_i32_lossy(request.status),
1834 limit: request.limit,
1835 summary_only: request.summary_only,
1836 }),
1837 )
1838 .await
1839 .map_err(|error| rpc_status("agent list turns", error))?;
1840 Ok(GrpcResponse::new(pb::ListAgentProviderTurnsResponse {
1841 turns: response
1842 .turns
1843 .into_iter()
1844 .map(turn_to_proto)
1845 .collect::<ProviderResult<Vec<_>>>()
1846 .map_err(|error| rpc_status("agent list turns", error))?,
1847 }))
1848 }
1849
1850 async fn cancel_turn(
1851 &self,
1852 request: GrpcRequest<pb::CancelAgentProviderTurnRequest>,
1853 ) -> std::result::Result<GrpcResponse<pb::AgentTurn>, Status> {
1854 let request = request.into_inner();
1855 let context = request.context.clone();
1856 let turn = scope_request_context(
1857 context,
1858 self.provider.cancel_turn(CancelAgentProviderTurnRequest {
1859 provider_name: request.provider_name,
1860 turn_id: request.turn_id,
1861 reason: request.reason,
1862 subject: agent_subject_from_proto(request.subject),
1863 }),
1864 )
1865 .await
1866 .map_err(|error| rpc_status("agent cancel turn", error))?;
1867 Ok(GrpcResponse::new(
1868 turn_to_proto(turn).map_err(|error| rpc_status("agent cancel turn", error))?,
1869 ))
1870 }
1871
1872 async fn list_turn_events(
1873 &self,
1874 request: GrpcRequest<pb::ListAgentProviderTurnEventsRequest>,
1875 ) -> std::result::Result<GrpcResponse<pb::ListAgentProviderTurnEventsResponse>, Status> {
1876 let request = request.into_inner();
1877 let context = request.context.clone();
1878 let response = scope_request_context(
1879 context,
1880 self.provider
1881 .list_turn_events(ListAgentProviderTurnEventsRequest {
1882 provider_name: request.provider_name,
1883 turn_id: request.turn_id,
1884 after_seq: request.after_seq,
1885 limit: request.limit,
1886 subject: agent_subject_from_proto(request.subject),
1887 }),
1888 )
1889 .await
1890 .map_err(|error| rpc_status("agent list turn events", error))?;
1891 Ok(GrpcResponse::new(pb::ListAgentProviderTurnEventsResponse {
1892 events: response
1893 .events
1894 .into_iter()
1895 .map(event_to_proto)
1896 .collect::<ProviderResult<Vec<_>>>()
1897 .map_err(|error| rpc_status("agent list turn events", error))?,
1898 }))
1899 }
1900
1901 async fn get_interaction(
1902 &self,
1903 request: GrpcRequest<pb::GetAgentProviderInteractionRequest>,
1904 ) -> std::result::Result<GrpcResponse<pb::AgentInteraction>, Status> {
1905 let request = request.into_inner();
1906 let context = request.context.clone();
1907 let interaction = scope_request_context(
1908 context,
1909 self.provider
1910 .get_interaction(GetAgentProviderInteractionRequest {
1911 interaction_id: request.interaction_id,
1912 subject: agent_subject_from_proto(request.subject),
1913 }),
1914 )
1915 .await
1916 .map_err(|error| rpc_status("agent get interaction", error))?;
1917 Ok(GrpcResponse::new(
1918 interaction_to_proto(interaction)
1919 .map_err(|error| rpc_status("agent get interaction", error))?,
1920 ))
1921 }
1922
1923 async fn list_interactions(
1924 &self,
1925 request: GrpcRequest<pb::ListAgentProviderInteractionsRequest>,
1926 ) -> std::result::Result<GrpcResponse<pb::ListAgentProviderInteractionsResponse>, Status> {
1927 let request = request.into_inner();
1928 let context = request.context.clone();
1929 let response = scope_request_context(
1930 context,
1931 self.provider
1932 .list_interactions(ListAgentProviderInteractionsRequest {
1933 provider_name: request.provider_name,
1934 turn_id: request.turn_id,
1935 subject: agent_subject_from_proto(request.subject),
1936 }),
1937 )
1938 .await
1939 .map_err(|error| rpc_status("agent list interactions", error))?;
1940 Ok(GrpcResponse::new(
1941 pb::ListAgentProviderInteractionsResponse {
1942 interactions: response
1943 .interactions
1944 .into_iter()
1945 .map(interaction_to_proto)
1946 .collect::<ProviderResult<Vec<_>>>()
1947 .map_err(|error| rpc_status("agent list interactions", error))?,
1948 },
1949 ))
1950 }
1951
1952 async fn resolve_interaction(
1953 &self,
1954 request: GrpcRequest<pb::ResolveAgentProviderInteractionRequest>,
1955 ) -> std::result::Result<GrpcResponse<pb::AgentInteraction>, Status> {
1956 let request = request.into_inner();
1957 let context = request.context.clone();
1958 let interaction = scope_request_context(
1959 context,
1960 self.provider
1961 .resolve_interaction(ResolveAgentProviderInteractionRequest {
1962 provider_name: request.provider_name,
1963 interaction_id: request.interaction_id,
1964 resolution: json_from_struct(request.resolution),
1965 subject: agent_subject_from_proto(request.subject),
1966 }),
1967 )
1968 .await
1969 .map_err(|error| rpc_status("agent resolve interaction", error))?;
1970 Ok(GrpcResponse::new(
1971 interaction_to_proto(interaction)
1972 .map_err(|error| rpc_status("agent resolve interaction", error))?,
1973 ))
1974 }
1975
1976 async fn get_capabilities(
1977 &self,
1978 _request: GrpcRequest<pb::GetAgentProviderCapabilitiesRequest>,
1979 ) -> std::result::Result<GrpcResponse<pb::AgentProviderCapabilities>, Status> {
1980 let capabilities = self
1981 .provider
1982 .get_capabilities(GetAgentProviderCapabilitiesRequest {})
1983 .await
1984 .map_err(|error| rpc_status("agent get capabilities", error))?;
1985 Ok(GrpcResponse::new(capabilities_to_proto(capabilities)))
1986 }
1987}