Add reply to the routes (#4963)
Co-authored-by: Douwe Osinga <douwe@squareup.com>
This commit is contained in:
@@ -346,6 +346,7 @@ derive_utoipa!(Icon as IconSchema);
|
||||
super::routes::agent::update_router_tool_selector,
|
||||
super::routes::agent::update_session_config,
|
||||
super::routes::reply::confirm_permission,
|
||||
super::routes::reply::reply,
|
||||
super::routes::context::manage_context,
|
||||
super::routes::session::list_sessions,
|
||||
super::routes::session::get_session,
|
||||
@@ -385,6 +386,7 @@ derive_utoipa!(Icon as IconSchema);
|
||||
super::routes::config_management::UpsertPermissionsQuery,
|
||||
super::routes::config_management::CreateCustomProviderRequest,
|
||||
super::routes::reply::PermissionConfirmationRequest,
|
||||
super::routes::reply::ChatRequest,
|
||||
super::routes::context::ContextManageRequest,
|
||||
super::routes::context::ContextManageResponse,
|
||||
super::routes::session::SessionListResponse,
|
||||
|
||||
@@ -10,16 +10,14 @@ use bytes::Bytes;
|
||||
use futures::{stream::StreamExt, Stream};
|
||||
use goose::conversation::message::{Message, MessageContent};
|
||||
use goose::conversation::Conversation;
|
||||
use goose::mcp_utils::ToolResult;
|
||||
use goose::permission::{Permission, PermissionConfirmation};
|
||||
use goose::session::SessionManager;
|
||||
use goose::{
|
||||
agents::{AgentEvent, SessionConfig},
|
||||
permission::permission_confirmation::PrincipalType,
|
||||
};
|
||||
use rmcp::model::{Content, ServerNotification};
|
||||
use rmcp::model::ServerNotification;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
use serde_json::Value;
|
||||
use std::{
|
||||
convert::Infallible,
|
||||
@@ -81,8 +79,8 @@ fn track_tool_telemetry(content: &MessageContent, all_messages: &[Message]) {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
struct ChatRequest {
|
||||
#[derive(Debug, Deserialize, Serialize, utoipa::ToSchema)]
|
||||
pub struct ChatRequest {
|
||||
messages: Vec<Message>,
|
||||
session_id: String,
|
||||
recipe_name: Option<String>,
|
||||
@@ -163,7 +161,18 @@ async fn stream_event(
|
||||
}
|
||||
}
|
||||
|
||||
async fn reply_handler(
|
||||
#[allow(clippy::too_many_lines)]
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/reply",
|
||||
request_body = ChatRequest,
|
||||
responses(
|
||||
(status = 200, description = "Streaming response initiated", content_type = "text/event-stream"),
|
||||
(status = 424, description = "Agent not initialized"),
|
||||
(status = 500, description = "Internal server error")
|
||||
)
|
||||
)]
|
||||
pub async fn reply(
|
||||
State(state): State<Arc<AppState>>,
|
||||
Json(request): Json<ChatRequest>,
|
||||
) -> Result<SseResponse, StatusCode> {
|
||||
@@ -446,50 +455,13 @@ pub async fn confirm_permission(
|
||||
Ok(Json(Value::Object(serde_json::Map::new())))
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct ToolResultRequest {
|
||||
id: String,
|
||||
result: ToolResult<Vec<Content>>,
|
||||
session_id: String,
|
||||
}
|
||||
|
||||
async fn submit_tool_result(
|
||||
State(state): State<Arc<AppState>>,
|
||||
raw: Json<Value>,
|
||||
) -> Result<Json<Value>, StatusCode> {
|
||||
tracing::info!(
|
||||
"Received tool result request: {}",
|
||||
serde_json::to_string_pretty(&raw.0).unwrap()
|
||||
);
|
||||
|
||||
let payload: ToolResultRequest = match serde_json::from_value(raw.0.clone()) {
|
||||
Ok(req) => req,
|
||||
Err(e) => {
|
||||
tracing::error!("Failed to parse tool result request: {}", e);
|
||||
tracing::error!(
|
||||
"Raw request was: {}",
|
||||
serde_json::to_string_pretty(&raw.0).unwrap()
|
||||
);
|
||||
return Err(StatusCode::UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
};
|
||||
|
||||
let agent = state.get_agent_for_route(payload.session_id).await?;
|
||||
agent.handle_tool_result(payload.id, payload.result).await;
|
||||
Ok(Json(json!({"status": "ok"})))
|
||||
}
|
||||
|
||||
pub fn routes(state: Arc<AppState>) -> Router {
|
||||
Router::new()
|
||||
.route(
|
||||
"/reply",
|
||||
post(reply_handler).layer(DefaultBodyLimit::max(50 * 1024 * 1024)),
|
||||
post(reply).layer(DefaultBodyLimit::max(50 * 1024 * 1024)),
|
||||
)
|
||||
.route("/confirm", post(confirm_permission))
|
||||
.route(
|
||||
"/tool_result",
|
||||
post(submit_tool_result).layer(DefaultBodyLimit::max(10 * 1024 * 1024)),
|
||||
)
|
||||
.with_state(state)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user