fix: async workspace memory backend

This commit is contained in:
2026-07-22 19:44:52 +09:00
parent aa542b38d9
commit fe2a39c12d
3 changed files with 167 additions and 133 deletions
+12 -11
View File
@@ -34,15 +34,15 @@ impl WorkspaceHttpMemoryBackend {
}
}
pub fn execute_operation(
pub async fn execute_operation(
&self,
operation: MemoryBackendOperation,
) -> Result<MemoryBackendOperationResult, WorkspaceMemoryBackendError> {
execute_http_memory_backend(&self.workspace_id, &self.base_url, operation)
execute_http_memory_backend(&self.workspace_id, &self.base_url, operation).await
}
fn execute(&self, operation: MemoryBackendOperation) -> Result<ToolOutput, ToolError> {
match self.execute_operation(operation) {
async fn execute(&self, operation: MemoryBackendOperation) -> Result<ToolOutput, ToolError> {
match self.execute_operation(operation).await {
Ok(MemoryBackendOperationResult::ToolOutput(output)) => Ok(tool_output(output)),
Ok(result) => Err(ToolError::ExecutionFailed(format!(
"unexpected memory backend result for model-visible tool: {result:?}"
@@ -70,7 +70,7 @@ pub enum WorkspaceMemoryBackendError {
}
impl WorkspaceClient {
pub fn execute_memory_backend_operation(
pub async fn execute_memory_backend_operation(
&self,
operation: MemoryBackendOperation,
) -> Result<MemoryBackendOperationResult, WorkspaceMemoryBackendError> {
@@ -78,7 +78,7 @@ impl WorkspaceClient {
WorkspaceClient::Http {
workspace_id,
base_url,
} => execute_http_memory_backend(workspace_id, base_url, operation),
} => execute_http_memory_backend(workspace_id, base_url, operation).await,
WorkspaceClient::Available { kind } => Err(WorkspaceMemoryBackendError::Unavailable {
reason: format!(
"workspace client kind `{kind}` does not expose the Backend Workspace API"
@@ -93,7 +93,7 @@ impl WorkspaceClient {
}
}
fn execute_http_memory_backend(
async fn execute_http_memory_backend(
workspace_id: &str,
base_url: &str,
operation: MemoryBackendOperation,
@@ -103,12 +103,13 @@ fn execute_http_memory_backend(
base_url.trim_end_matches('/'),
workspace_id
);
let response = reqwest::blocking::Client::new()
let response = reqwest::Client::new()
.post(url)
.json(&operation)
.send()?;
.send()
.await?;
let status = response.status();
let body = response.text()?;
let body = response.text().await?;
if !status.is_success() {
return Err(WorkspaceMemoryBackendError::Http { status, body });
}
@@ -220,7 +221,7 @@ impl Tool for WorkspaceHttpMemoryTool {
_ctx: ToolExecutionContext,
) -> Result<ToolOutput, ToolError> {
let operation = (self.build)(input_json)?;
self.backend.execute(operation)
self.backend.execute(operation).await
}
}
@@ -433,6 +433,7 @@ impl Tool for StageCandidateTool {
source_refs,
},
))
.await
.map_err(|e| ToolError::ExecutionFailed(format!("write staging failed: {e}")))?;
let ids = match result {
MemoryBackendOperationResult::StagingWritten(output) if output.staging_count == 1 => {
@@ -713,7 +714,7 @@ mod tests {
#[tokio::test]
async fn stage_candidate_writes_staging_record_with_source_evidence() {
let (client, request_rx) = stub_memory_backend_response(
r#"{"Ok":{"result":{"StagingWritten":{"staging_count":1,"staging_ids":["00000000-0000-7000-8000-000000000001"]}}}}"#,
r#"{"status":"ok","result":{"kind":"staging_written","staging_count":1,"staging_ids":["00000000-0000-7000-8000-000000000001"]}}"#,
);
let state = SessionExploreState::new(
SessionReferenceView::new("segment-1", vec![Item::user_message("durable decision")]),
@@ -745,7 +746,7 @@ mod tests {
vec!["00000000-0000-7000-8000-000000000001".to_string()]
);
let request = request_rx.recv().unwrap();
assert!(request.contains("\"StageCandidate\""));
assert!(request.contains("\"operation\":\"stage_candidate\""));
assert!(request.contains("\"kind\":\"decision\""));
assert!(request.contains("\"id\":\"M0000\""));
assert!(request.contains("\"evidence_id\":\"M0000\""));