agent_first_http/sdk/
takeover.rs1use serde::{Deserialize, Serialize};
4
5use crate::sdk::client::Client;
6use crate::shared::error::{Error, ErrorCode};
7
8#[derive(Debug, Clone, Serialize)]
9struct TakeoverHandoffRequest<'a> {
10 #[serde(skip_serializing_if = "Option::is_none")]
11 ttl_s: Option<u64>,
12 #[serde(skip_serializing_if = "Option::is_none")]
13 tab_id: Option<&'a str>,
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
17pub struct TakeoverHandoffResponse {
18 #[serde(alias = "takeover_url")]
19 pub takeover_url_secret: String,
20 pub takeover_url_expires_at_rfc3339: String,
21 pub takeover_url_ttl_s: u64,
22 pub takeover_url_scope: String,
23}
24
25impl Client {
26 pub async fn takeover_handoff(
28 &self,
29 ttl_s: Option<u64>,
30 tab_id: Option<&str>,
31 ) -> Result<TakeoverHandoffResponse, Error> {
32 let endpoint = self.effective_endpoint().await?;
33 let base = endpoint.http_base();
34 let url = format!("{base}/takeover/handoff");
35 let body = TakeoverHandoffRequest { ttl_s, tab_id };
36 let mut req = self.http().post(&url).json(&body);
37 if let Some(token) = self.token() {
38 req = req.bearer_auth(token);
39 }
40 let resp = req
41 .send()
42 .await
43 .map_err(|e| Error::new(ErrorCode::HostUnreachable, format!("POST {url}: {e}")))?;
44 let status = resp.status();
45 let bytes = resp.bytes().await.map_err(|e| {
46 Error::new(
47 ErrorCode::InternalError,
48 format!("takeover_handoff: read response: {e}"),
49 )
50 })?;
51 if !status.is_success() {
52 if let Ok(err) = crate::shared::afdata::decode_error(&bytes) {
53 return Err(err);
54 }
55 return Err(Error::new(
56 ErrorCode::InternalError,
57 format!(
58 "takeover_handoff: status {status}; failed to decode error envelope: {}",
59 String::from_utf8_lossy(&bytes)
60 ),
61 ));
62 }
63 crate::shared::afdata::decode_result(&bytes)
64 }
65}