mirror of
https://github.com/block/goose.git
synced 2026-07-17 12:56:20 +02:00
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)
|
||||
}
|
||||
|
||||
|
||||
@@ -1206,6 +1206,35 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/reply": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"super::routes::reply"
|
||||
],
|
||||
"operationId": "reply",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ChatRequest"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Streaming response initiated"
|
||||
},
|
||||
"424": {
|
||||
"description": "Agent not initialized"
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/schedule/create": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@@ -1845,6 +1874,32 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"ChatRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"messages",
|
||||
"session_id"
|
||||
],
|
||||
"properties": {
|
||||
"messages": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Message"
|
||||
}
|
||||
},
|
||||
"recipe_name": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"recipe_version": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"session_id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ConfigKey": {
|
||||
"type": "object",
|
||||
"description": "Configuration key metadata for provider setup",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
import type { Options as ClientOptions, TDataShape, Client } from './client';
|
||||
import type { AddSubRecipesData, AddSubRecipesResponses, AddSubRecipesErrors, ExtendPromptData, ExtendPromptResponses, ExtendPromptErrors, ResumeAgentData, ResumeAgentResponses, ResumeAgentErrors, UpdateSessionConfigData, UpdateSessionConfigResponses, UpdateSessionConfigErrors, StartAgentData, StartAgentResponses, StartAgentErrors, GetToolsData, GetToolsResponses, GetToolsErrors, UpdateAgentProviderData, UpdateAgentProviderResponses, UpdateAgentProviderErrors, UpdateRouterToolSelectorData, UpdateRouterToolSelectorResponses, UpdateRouterToolSelectorErrors, ReadAllConfigData, ReadAllConfigResponses, BackupConfigData, BackupConfigResponses, BackupConfigErrors, CreateCustomProviderData, CreateCustomProviderResponses, CreateCustomProviderErrors, RemoveCustomProviderData, RemoveCustomProviderResponses, RemoveCustomProviderErrors, GetExtensionsData, GetExtensionsResponses, GetExtensionsErrors, AddExtensionData, AddExtensionResponses, AddExtensionErrors, RemoveExtensionData, RemoveExtensionResponses, RemoveExtensionErrors, InitConfigData, InitConfigResponses, InitConfigErrors, UpsertPermissionsData, UpsertPermissionsResponses, UpsertPermissionsErrors, ProvidersData, ProvidersResponses, GetProviderModelsData, GetProviderModelsResponses, GetProviderModelsErrors, ReadConfigData, ReadConfigResponses, ReadConfigErrors, RecoverConfigData, RecoverConfigResponses, RecoverConfigErrors, RemoveConfigData, RemoveConfigResponses, RemoveConfigErrors, UpsertConfigData, UpsertConfigResponses, UpsertConfigErrors, ValidateConfigData, ValidateConfigResponses, ValidateConfigErrors, ConfirmPermissionData, ConfirmPermissionResponses, ConfirmPermissionErrors, ManageContextData, ManageContextResponses, ManageContextErrors, StartOpenrouterSetupData, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponses, CreateRecipeData, CreateRecipeResponses, CreateRecipeErrors, DecodeRecipeData, DecodeRecipeResponses, DecodeRecipeErrors, DeleteRecipeData, DeleteRecipeResponses, DeleteRecipeErrors, EncodeRecipeData, EncodeRecipeResponses, EncodeRecipeErrors, ListRecipesData, ListRecipesResponses, ListRecipesErrors, ParseRecipeData, ParseRecipeResponses, ParseRecipeErrors, SaveRecipeData, SaveRecipeResponses, SaveRecipeErrors, ScanRecipeData, ScanRecipeResponses, CreateScheduleData, CreateScheduleResponses, CreateScheduleErrors, DeleteScheduleData, DeleteScheduleResponses, DeleteScheduleErrors, ListSchedulesData, ListSchedulesResponses, ListSchedulesErrors, UpdateScheduleData, UpdateScheduleResponses, UpdateScheduleErrors, InspectRunningJobData, InspectRunningJobResponses, InspectRunningJobErrors, KillRunningJobData, KillRunningJobResponses, PauseScheduleData, PauseScheduleResponses, PauseScheduleErrors, RunNowHandlerData, RunNowHandlerResponses, RunNowHandlerErrors, SessionsHandlerData, SessionsHandlerResponses, SessionsHandlerErrors, UnpauseScheduleData, UnpauseScheduleResponses, UnpauseScheduleErrors, ListSessionsData, ListSessionsResponses, ListSessionsErrors, GetSessionInsightsData, GetSessionInsightsResponses, GetSessionInsightsErrors, DeleteSessionData, DeleteSessionResponses, DeleteSessionErrors, GetSessionData, GetSessionResponses, GetSessionErrors, UpdateSessionDescriptionData, UpdateSessionDescriptionResponses, UpdateSessionDescriptionErrors, StatusData, StatusResponses } from './types.gen';
|
||||
import type { AddSubRecipesData, AddSubRecipesResponses, AddSubRecipesErrors, ExtendPromptData, ExtendPromptResponses, ExtendPromptErrors, ResumeAgentData, ResumeAgentResponses, ResumeAgentErrors, UpdateSessionConfigData, UpdateSessionConfigResponses, UpdateSessionConfigErrors, StartAgentData, StartAgentResponses, StartAgentErrors, GetToolsData, GetToolsResponses, GetToolsErrors, UpdateAgentProviderData, UpdateAgentProviderResponses, UpdateAgentProviderErrors, UpdateRouterToolSelectorData, UpdateRouterToolSelectorResponses, UpdateRouterToolSelectorErrors, ReadAllConfigData, ReadAllConfigResponses, BackupConfigData, BackupConfigResponses, BackupConfigErrors, CreateCustomProviderData, CreateCustomProviderResponses, CreateCustomProviderErrors, RemoveCustomProviderData, RemoveCustomProviderResponses, RemoveCustomProviderErrors, GetExtensionsData, GetExtensionsResponses, GetExtensionsErrors, AddExtensionData, AddExtensionResponses, AddExtensionErrors, RemoveExtensionData, RemoveExtensionResponses, RemoveExtensionErrors, InitConfigData, InitConfigResponses, InitConfigErrors, UpsertPermissionsData, UpsertPermissionsResponses, UpsertPermissionsErrors, ProvidersData, ProvidersResponses, GetProviderModelsData, GetProviderModelsResponses, GetProviderModelsErrors, ReadConfigData, ReadConfigResponses, ReadConfigErrors, RecoverConfigData, RecoverConfigResponses, RecoverConfigErrors, RemoveConfigData, RemoveConfigResponses, RemoveConfigErrors, UpsertConfigData, UpsertConfigResponses, UpsertConfigErrors, ValidateConfigData, ValidateConfigResponses, ValidateConfigErrors, ConfirmPermissionData, ConfirmPermissionResponses, ConfirmPermissionErrors, ManageContextData, ManageContextResponses, ManageContextErrors, StartOpenrouterSetupData, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponses, CreateRecipeData, CreateRecipeResponses, CreateRecipeErrors, DecodeRecipeData, DecodeRecipeResponses, DecodeRecipeErrors, DeleteRecipeData, DeleteRecipeResponses, DeleteRecipeErrors, EncodeRecipeData, EncodeRecipeResponses, EncodeRecipeErrors, ListRecipesData, ListRecipesResponses, ListRecipesErrors, ParseRecipeData, ParseRecipeResponses, ParseRecipeErrors, SaveRecipeData, SaveRecipeResponses, SaveRecipeErrors, ScanRecipeData, ScanRecipeResponses, ReplyData, ReplyResponses, ReplyErrors, CreateScheduleData, CreateScheduleResponses, CreateScheduleErrors, DeleteScheduleData, DeleteScheduleResponses, DeleteScheduleErrors, ListSchedulesData, ListSchedulesResponses, ListSchedulesErrors, UpdateScheduleData, UpdateScheduleResponses, UpdateScheduleErrors, InspectRunningJobData, InspectRunningJobResponses, InspectRunningJobErrors, KillRunningJobData, KillRunningJobResponses, PauseScheduleData, PauseScheduleResponses, PauseScheduleErrors, RunNowHandlerData, RunNowHandlerResponses, RunNowHandlerErrors, SessionsHandlerData, SessionsHandlerResponses, SessionsHandlerErrors, UnpauseScheduleData, UnpauseScheduleResponses, UnpauseScheduleErrors, ListSessionsData, ListSessionsResponses, ListSessionsErrors, GetSessionInsightsData, GetSessionInsightsResponses, GetSessionInsightsErrors, DeleteSessionData, DeleteSessionResponses, DeleteSessionErrors, GetSessionData, GetSessionResponses, GetSessionErrors, UpdateSessionDescriptionData, UpdateSessionDescriptionResponses, UpdateSessionDescriptionErrors, StatusData, StatusResponses } from './types.gen';
|
||||
import { client as _heyApiClient } from './client.gen';
|
||||
|
||||
export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = ClientOptions<TData, ThrowOnError> & {
|
||||
@@ -361,6 +361,17 @@ export const scanRecipe = <ThrowOnError extends boolean = false>(options: Option
|
||||
});
|
||||
};
|
||||
|
||||
export const reply = <ThrowOnError extends boolean = false>(options: Options<ReplyData, ThrowOnError>) => {
|
||||
return (options.client ?? _heyApiClient).post<ReplyResponses, ReplyErrors, ThrowOnError>({
|
||||
url: '/reply',
|
||||
...options,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...options.headers
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const createSchedule = <ThrowOnError extends boolean = false>(options: Options<CreateScheduleData, ThrowOnError>) => {
|
||||
return (options.client ?? _heyApiClient).post<CreateScheduleResponses, CreateScheduleErrors, ThrowOnError>({
|
||||
url: '/schedule/create',
|
||||
|
||||
@@ -25,6 +25,13 @@ export type AuthorRequest = {
|
||||
metadata?: string | null;
|
||||
};
|
||||
|
||||
export type ChatRequest = {
|
||||
messages: Array<Message>;
|
||||
recipe_name?: string | null;
|
||||
recipe_version?: string | null;
|
||||
session_id: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Configuration key metadata for provider setup
|
||||
*/
|
||||
@@ -1871,6 +1878,31 @@ export type ScanRecipeResponses = {
|
||||
|
||||
export type ScanRecipeResponse2 = ScanRecipeResponses[keyof ScanRecipeResponses];
|
||||
|
||||
export type ReplyData = {
|
||||
body: ChatRequest;
|
||||
path?: never;
|
||||
query?: never;
|
||||
url: '/reply';
|
||||
};
|
||||
|
||||
export type ReplyErrors = {
|
||||
/**
|
||||
* Agent not initialized
|
||||
*/
|
||||
424: unknown;
|
||||
/**
|
||||
* Internal server error
|
||||
*/
|
||||
500: unknown;
|
||||
};
|
||||
|
||||
export type ReplyResponses = {
|
||||
/**
|
||||
* Streaming response initiated
|
||||
*/
|
||||
200: unknown;
|
||||
};
|
||||
|
||||
export type CreateScheduleData = {
|
||||
body: CreateScheduleRequest;
|
||||
path?: never;
|
||||
|
||||
Reference in New Issue
Block a user