ACP over MCP server impl (#35196)
Release Notes: - N/A --------- Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
This commit is contained in:
parent
b02ae771cd
commit
c2fc70eef7
20 changed files with 899 additions and 137 deletions
|
@ -330,23 +330,16 @@ impl Client {
|
|||
method: &str,
|
||||
params: impl Serialize,
|
||||
) -> Result<T> {
|
||||
self.request_impl(method, params, None).await
|
||||
self.request_with(method, params, None, Some(REQUEST_TIMEOUT))
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn cancellable_request<T: DeserializeOwned>(
|
||||
&self,
|
||||
method: &str,
|
||||
params: impl Serialize,
|
||||
cancel_rx: oneshot::Receiver<()>,
|
||||
) -> Result<T> {
|
||||
self.request_impl(method, params, Some(cancel_rx)).await
|
||||
}
|
||||
|
||||
pub async fn request_impl<T: DeserializeOwned>(
|
||||
pub async fn request_with<T: DeserializeOwned>(
|
||||
&self,
|
||||
method: &str,
|
||||
params: impl Serialize,
|
||||
cancel_rx: Option<oneshot::Receiver<()>>,
|
||||
timeout: Option<Duration>,
|
||||
) -> Result<T> {
|
||||
let id = self.next_id.fetch_add(1, SeqCst);
|
||||
let request = serde_json::to_string(&Request {
|
||||
|
@ -382,7 +375,13 @@ impl Client {
|
|||
handle_response?;
|
||||
send?;
|
||||
|
||||
let mut timeout = executor.timer(REQUEST_TIMEOUT).fuse();
|
||||
let mut timeout_fut = pin!(
|
||||
match timeout {
|
||||
Some(timeout) => future::Either::Left(executor.timer(timeout)),
|
||||
None => future::Either::Right(future::pending()),
|
||||
}
|
||||
.fuse()
|
||||
);
|
||||
let mut cancel_fut = pin!(
|
||||
match cancel_rx {
|
||||
Some(rx) => future::Either::Left(async {
|
||||
|
@ -419,10 +418,10 @@ impl Client {
|
|||
reason: None
|
||||
})
|
||||
).log_err();
|
||||
anyhow::bail!("Request cancelled")
|
||||
anyhow::bail!(RequestCanceled)
|
||||
}
|
||||
_ = timeout => {
|
||||
log::error!("cancelled csp request task for {method:?} id {id} which took over {:?}", REQUEST_TIMEOUT);
|
||||
_ = timeout_fut => {
|
||||
log::error!("cancelled csp request task for {method:?} id {id} which took over {:?}", timeout.unwrap());
|
||||
anyhow::bail!("Context server request timeout");
|
||||
}
|
||||
}
|
||||
|
@ -452,6 +451,17 @@ impl Client {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RequestCanceled;
|
||||
|
||||
impl std::error::Error for RequestCanceled {}
|
||||
|
||||
impl std::fmt::Display for RequestCanceled {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str("Context server request was canceled")
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ContextServerId {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
|
|
|
@ -419,7 +419,7 @@ pub struct ToolResponse<T> {
|
|||
pub structured_content: T,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct RawRequest {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
id: Option<RequestId>,
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
//! read/write messages and the types from types.rs for serialization/deserialization
|
||||
//! of messages.
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use futures::channel::oneshot;
|
||||
use gpui::AsyncApp;
|
||||
|
@ -98,13 +100,14 @@ impl InitializedContextServerProtocol {
|
|||
self.inner.request(T::METHOD, params).await
|
||||
}
|
||||
|
||||
pub async fn cancellable_request<T: Request>(
|
||||
pub async fn request_with<T: Request>(
|
||||
&self,
|
||||
params: T::Params,
|
||||
cancel_rx: oneshot::Receiver<()>,
|
||||
cancel_rx: Option<oneshot::Receiver<()>>,
|
||||
timeout: Option<Duration>,
|
||||
) -> Result<T::Response> {
|
||||
self.inner
|
||||
.cancellable_request(T::METHOD, params, cancel_rx)
|
||||
.request_with(T::METHOD, params, cancel_rx, timeout)
|
||||
.await
|
||||
}
|
||||
|
||||
|
|
|
@ -626,6 +626,7 @@ pub enum ClientNotification {
|
|||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CancelledParams {
|
||||
pub request_id: RequestId,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
|
@ -685,6 +686,18 @@ pub struct CallToolResponse {
|
|||
pub structured_content: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
impl CallToolResponse {
|
||||
pub fn text_contents(&self) -> String {
|
||||
let mut text = String::new();
|
||||
for chunk in &self.content {
|
||||
if let ToolResponseContent::Text { text: chunk } = chunk {
|
||||
text.push_str(&chunk)
|
||||
};
|
||||
}
|
||||
text
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum ToolResponseContent {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue