codex_runtime/runtime/core/
rpc.rs1use serde::{de::DeserializeOwned, Serialize};
2use serde_json::Value;
3use tokio::time::Duration;
4
5use crate::runtime::errors::{RpcError, RuntimeError};
6use crate::runtime::rpc_contract::{
7 validate_rpc_request, validate_rpc_response, RpcValidationMode,
8};
9
10use super::rpc_io::{call_raw_inner, notify_raw_inner};
11use super::Runtime;
12
13impl Runtime {
14 pub async fn call_raw(&self, method: &str, params: Value) -> Result<Value, RpcError> {
15 self.call_raw_internal(method, params, true, self.inner.spec.rpc_response_timeout)
16 .await
17 }
18
19 pub async fn call_validated(&self, method: &str, params: Value) -> Result<Value, RpcError> {
22 self.call_validated_with_mode(method, params, RpcValidationMode::KnownMethods)
23 .await
24 }
25
26 pub async fn call_validated_with_mode(
28 &self,
29 method: &str,
30 params: Value,
31 mode: RpcValidationMode,
32 ) -> Result<Value, RpcError> {
33 self.call_validated_with_mode_and_timeout(
34 method,
35 params,
36 mode,
37 self.inner.spec.rpc_response_timeout,
38 )
39 .await
40 }
41
42 pub(crate) async fn call_validated_with_mode_and_timeout(
43 &self,
44 method: &str,
45 params: Value,
46 mode: RpcValidationMode,
47 timeout_duration: Duration,
48 ) -> Result<Value, RpcError> {
49 validate_rpc_request(method, ¶ms, mode)?;
50 let result = self
51 .call_raw_internal(method, params, true, timeout_duration)
52 .await?;
53 validate_rpc_response(method, &result, mode)?;
54 Ok(result)
55 }
56
57 #[cfg(test)]
58 pub(crate) async fn call_raw_with_timeout(
59 &self,
60 method: &str,
61 params: Value,
62 timeout_duration: Duration,
63 ) -> Result<Value, RpcError> {
64 self.call_raw_internal(method, params, true, timeout_duration)
65 .await
66 }
67
68 pub async fn call_typed_validated<P, R>(&self, method: &str, params: P) -> Result<R, RpcError>
70 where
71 P: Serialize,
72 R: DeserializeOwned,
73 {
74 self.call_typed_validated_with_mode(method, params, RpcValidationMode::KnownMethods)
75 .await
76 }
77
78 pub async fn call_typed_validated_with_mode<P, R>(
80 &self,
81 method: &str,
82 params: P,
83 mode: RpcValidationMode,
84 ) -> Result<R, RpcError>
85 where
86 P: Serialize,
87 R: DeserializeOwned,
88 {
89 let params_value = serde_json::to_value(params).map_err(|err| {
90 RpcError::InvalidRequest(format!(
91 "failed to serialize json-rpc params for {method}: {err}"
92 ))
93 })?;
94 let result = self
95 .call_validated_with_mode(method, params_value, mode)
96 .await?;
97 serde_json::from_value(result).map_err(|err| {
98 RpcError::InvalidRequest(format!(
99 "failed to deserialize json-rpc result for {method}: {err}"
100 ))
101 })
102 }
103
104 pub async fn notify_raw(&self, method: &str, params: Value) -> Result<(), RuntimeError> {
105 self.notify_raw_internal(method, params, true).await
106 }
107
108 pub async fn notify_validated(&self, method: &str, params: Value) -> Result<(), RuntimeError> {
110 self.notify_validated_with_mode(method, params, RpcValidationMode::KnownMethods)
111 .await
112 }
113
114 pub async fn notify_validated_with_mode(
116 &self,
117 method: &str,
118 params: Value,
119 mode: RpcValidationMode,
120 ) -> Result<(), RuntimeError> {
121 validate_rpc_request(method, ¶ms, mode).map_err(|err| {
122 RuntimeError::InvalidConfig(format!("invalid json-rpc notify payload: {err}"))
123 })?;
124 self.notify_raw_internal(method, params, true).await
125 }
126
127 pub async fn notify_typed_validated<P>(
129 &self,
130 method: &str,
131 params: P,
132 ) -> Result<(), RuntimeError>
133 where
134 P: Serialize,
135 {
136 self.notify_typed_validated_with_mode(method, params, RpcValidationMode::KnownMethods)
137 .await
138 }
139
140 pub async fn notify_typed_validated_with_mode<P>(
142 &self,
143 method: &str,
144 params: P,
145 mode: RpcValidationMode,
146 ) -> Result<(), RuntimeError>
147 where
148 P: Serialize,
149 {
150 let params_value = serde_json::to_value(params).map_err(|err| {
151 RuntimeError::InvalidConfig(format!(
152 "invalid json-rpc notify payload: failed to serialize json-rpc params for {method}: {err}"
153 ))
154 })?;
155 self.notify_validated_with_mode(method, params_value, mode)
156 .await
157 }
158
159 async fn call_raw_internal(
160 &self,
161 method: &str,
162 params: Value,
163 require_initialized: bool,
164 timeout_duration: Duration,
165 ) -> Result<Value, RpcError> {
166 if require_initialized && !self.is_initialized() {
167 return Err(RpcError::InvalidRequest(
168 "runtime is not initialized".to_owned(),
169 ));
170 }
171
172 call_raw_inner(&self.inner, method, params, timeout_duration).await
173 }
174
175 async fn notify_raw_internal(
176 &self,
177 method: &str,
178 params: Value,
179 require_initialized: bool,
180 ) -> Result<(), RuntimeError> {
181 if require_initialized && !self.is_initialized() {
182 return Err(RuntimeError::NotInitialized);
183 }
184
185 notify_raw_inner(&self.inner, method, params).await
186 }
187}