Reroute routes (#4088)
Co-authored-by: Douwe Osinga <douwe@squareup.com> Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -369,6 +369,10 @@ impl<'__s> ToSchema<'__s> for AnnotatedSchema {
|
||||
super::routes::config_management::upsert_permissions,
|
||||
super::routes::agent::get_tools,
|
||||
super::routes::agent::add_sub_recipes,
|
||||
super::routes::agent::extend_prompt,
|
||||
super::routes::agent::update_agent_provider,
|
||||
super::routes::agent::update_router_tool_selector,
|
||||
super::routes::agent::update_session_config,
|
||||
super::routes::reply::confirm_permission,
|
||||
super::routes::context::manage_context,
|
||||
super::routes::session::list_sessions,
|
||||
@@ -464,6 +468,12 @@ impl<'__s> ToSchema<'__s> for AnnotatedSchema {
|
||||
goose::agents::types::SuccessCheck,
|
||||
super::routes::agent::AddSubRecipesRequest,
|
||||
super::routes::agent::AddSubRecipesResponse,
|
||||
super::routes::agent::ExtendPromptRequest,
|
||||
super::routes::agent::ExtendPromptResponse,
|
||||
super::routes::agent::UpdateProviderRequest,
|
||||
super::routes::agent::SessionConfigRequest,
|
||||
super::routes::agent::GetToolsQuery,
|
||||
super::routes::agent::ErrorResponse,
|
||||
))
|
||||
)]
|
||||
pub struct ApiDoc;
|
||||
|
||||
@@ -16,22 +16,15 @@ use goose::{
|
||||
};
|
||||
use goose::{config::Config, recipe::SubRecipe};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct VersionsResponse {
|
||||
available_versions: Vec<String>,
|
||||
default_version: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ExtendPromptRequest {
|
||||
#[derive(Deserialize, utoipa::ToSchema)]
|
||||
pub struct ExtendPromptRequest {
|
||||
extension: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ExtendPromptResponse {
|
||||
#[derive(Serialize, utoipa::ToSchema)]
|
||||
pub struct ExtendPromptResponse {
|
||||
success: bool,
|
||||
}
|
||||
|
||||
@@ -45,66 +38,35 @@ pub struct AddSubRecipesResponse {
|
||||
success: bool,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ProviderFile {
|
||||
name: String,
|
||||
description: String,
|
||||
models: Vec<String>,
|
||||
required_keys: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ProviderDetails {
|
||||
name: String,
|
||||
description: String,
|
||||
models: Vec<String>,
|
||||
required_keys: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ProviderList {
|
||||
id: String,
|
||||
details: ProviderDetails,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct UpdateProviderRequest {
|
||||
#[derive(Deserialize, utoipa::ToSchema)]
|
||||
pub struct UpdateProviderRequest {
|
||||
provider: String,
|
||||
model: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct SessionConfigRequest {
|
||||
#[derive(Deserialize, utoipa::ToSchema)]
|
||||
pub struct SessionConfigRequest {
|
||||
response: Option<Response>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[derive(Deserialize, utoipa::ToSchema)]
|
||||
pub struct GetToolsQuery {
|
||||
extension_name: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ErrorResponse {
|
||||
#[derive(Serialize, utoipa::ToSchema)]
|
||||
pub struct ErrorResponse {
|
||||
error: String,
|
||||
}
|
||||
|
||||
async fn get_versions() -> Json<VersionsResponse> {
|
||||
let versions = ["goose".to_string()];
|
||||
let default_version = "goose".to_string();
|
||||
|
||||
Json(VersionsResponse {
|
||||
available_versions: versions.iter().map(|v| v.to_string()).collect(),
|
||||
default_version,
|
||||
})
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/agent/add_sub_recipes",
|
||||
request_body = AddSubRecipesRequest,
|
||||
responses(
|
||||
(status = 200, description = "added sub recipes to agent successfully", body = AddSubRecipesResponse),
|
||||
(status = 200, description = "Added sub recipes to agent successfully", body = AddSubRecipesResponse),
|
||||
(status = 401, description = "Unauthorized - invalid secret key"),
|
||||
(status = 424, description = "Agent not initialized"),
|
||||
),
|
||||
)]
|
||||
async fn add_sub_recipes(
|
||||
@@ -122,6 +84,16 @@ async fn add_sub_recipes(
|
||||
Ok(Json(AddSubRecipesResponse { success: true }))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/agent/prompt",
|
||||
request_body = ExtendPromptRequest,
|
||||
responses(
|
||||
(status = 200, description = "Extended system prompt successfully", body = ExtendPromptResponse),
|
||||
(status = 401, description = "Unauthorized - invalid secret key"),
|
||||
(status = 424, description = "Agent not initialized"),
|
||||
),
|
||||
)]
|
||||
async fn extend_prompt(
|
||||
State(state): State<Arc<AppState>>,
|
||||
headers: HeaderMap,
|
||||
@@ -137,29 +109,6 @@ async fn extend_prompt(
|
||||
Ok(Json(ExtendPromptResponse { success: true }))
|
||||
}
|
||||
|
||||
async fn list_providers() -> Json<Vec<ProviderList>> {
|
||||
let contents = include_str!("providers_and_keys.json");
|
||||
|
||||
let providers: HashMap<String, ProviderFile> =
|
||||
serde_json::from_str(contents).expect("Failed to parse providers_and_keys.json");
|
||||
|
||||
let response: Vec<ProviderList> = providers
|
||||
.into_iter()
|
||||
.map(|(id, provider)| ProviderList {
|
||||
id,
|
||||
details: ProviderDetails {
|
||||
name: provider.name,
|
||||
description: provider.description,
|
||||
models: provider.models,
|
||||
required_keys: provider.required_keys,
|
||||
},
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Return the response as JSON.
|
||||
Json(response)
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/agent/tools",
|
||||
@@ -224,10 +173,12 @@ async fn get_tools(
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/agent/update_provider",
|
||||
request_body = UpdateProviderRequest,
|
||||
responses(
|
||||
(status = 200, description = "Update provider completed", body = String),
|
||||
(status = 200, description = "Provider updated successfully"),
|
||||
(status = 400, description = "Bad request - missing or invalid parameters"),
|
||||
(status = 401, description = "Unauthorized - invalid secret key"),
|
||||
(status = 424, description = "Agent not initialized"),
|
||||
(status = 500, description = "Internal server error")
|
||||
)
|
||||
)]
|
||||
@@ -269,6 +220,8 @@ async fn update_agent_provider(
|
||||
path = "/agent/update_router_tool_selector",
|
||||
responses(
|
||||
(status = 200, description = "Tool selection strategy updated successfully", body = String),
|
||||
(status = 401, description = "Unauthorized - invalid secret key"),
|
||||
(status = 424, description = "Agent not initialized"),
|
||||
(status = 500, description = "Internal server error")
|
||||
)
|
||||
)]
|
||||
@@ -307,8 +260,11 @@ async fn update_router_tool_selector(
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/agent/session_config",
|
||||
request_body = SessionConfigRequest,
|
||||
responses(
|
||||
(status = 200, description = "Session config updated successfully", body = String),
|
||||
(status = 401, description = "Unauthorized - invalid secret key"),
|
||||
(status = 424, description = "Agent not initialized"),
|
||||
(status = 500, description = "Internal server error")
|
||||
)
|
||||
)]
|
||||
@@ -344,8 +300,6 @@ async fn update_session_config(
|
||||
|
||||
pub fn routes(state: Arc<AppState>) -> Router {
|
||||
Router::new()
|
||||
.route("/agent/versions", get(get_versions))
|
||||
.route("/agent/providers", get(list_providers))
|
||||
.route("/agent/prompt", post(extend_prompt))
|
||||
.route("/agent/tools", get(get_tools))
|
||||
.route("/agent/update_provider", post(update_agent_provider))
|
||||
|
||||
@@ -58,9 +58,7 @@ pub struct ConfigResponse {
|
||||
#[derive(Debug, Serialize, Deserialize, ToSchema)]
|
||||
pub struct ProviderDetails {
|
||||
pub name: String,
|
||||
|
||||
pub metadata: ProviderMetadata,
|
||||
|
||||
pub is_configured: bool,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
{
|
||||
"openai": {
|
||||
"name": "OpenAI",
|
||||
"description": "Use GPT-4 and other OpenAI models",
|
||||
"models": ["gpt-4o", "gpt-4-turbo","o1"],
|
||||
"required_keys": ["OPENAI_API_KEY", "OPENAI_HOST", "OPENAI_BASE_PATH"]
|
||||
},
|
||||
"anthropic": {
|
||||
"name": "Anthropic",
|
||||
"description": "Use Claude and other Anthropic models",
|
||||
"models": ["claude-3.5-sonnet-2"],
|
||||
"required_keys": ["ANTHROPIC_API_KEY", "ANTHROPIC_HOST"]
|
||||
},
|
||||
"databricks": {
|
||||
"name": "Databricks",
|
||||
"description": "Connect to LLMs via Databricks",
|
||||
"models": ["goose"],
|
||||
"required_keys": ["DATABRICKS_HOST"]
|
||||
},
|
||||
"gcp_vertex_ai": {
|
||||
"name": "GCP Vertex AI",
|
||||
"description": "Use Vertex AI platform models",
|
||||
"models": ["claude-3-5-haiku@20241022", "claude-3-5-sonnet@20240620", "claude-3-5-sonnet-v2@20241022", "claude-3-7-sonnet@20250219", "claude-sonnet-4@20250514", "claude-opus-4@20250514", "gemini-1.5-pro-002", "gemini-2.0-flash-001", "gemini-2.0-pro-exp-02-05", "gemini-2.5-pro-exp-03-25", "gemini-2.5-flash-preview-05-20", "gemini-2.5-pro-preview-05-06", "gemini-2.5-flash", "gemini-2.5-pro"],
|
||||
"required_keys": ["GCP_PROJECT_ID", "GCP_LOCATION"]
|
||||
},
|
||||
"google": {
|
||||
"name": "Google",
|
||||
"description": "Lorem ipsum",
|
||||
"models": ["gemini-1.5-flash"],
|
||||
"required_keys": ["GOOGLE_API_KEY"]
|
||||
},
|
||||
"groq": {
|
||||
"name": "Groq",
|
||||
"description": "Lorem ipsum",
|
||||
"models": ["llama-3.3-70b-versatile"],
|
||||
"required_keys": ["GROQ_API_KEY"]
|
||||
},
|
||||
"ollama": {
|
||||
"name": "Ollama",
|
||||
"description": "Lorem ipsum",
|
||||
"models": ["qwen2.5"],
|
||||
"required_keys": ["OLLAMA_HOST"]
|
||||
},
|
||||
"openrouter": {
|
||||
"name": "OpenRouter",
|
||||
"description": "Lorem ipsum",
|
||||
"models": [],
|
||||
"required_keys": ["OPENROUTER_API_KEY"]
|
||||
},
|
||||
"azure_openai": {
|
||||
"name": "Azure OpenAI",
|
||||
"description": "Connect to Azure OpenAI Service. If no API key is provided, Azure credential chain will be used.",
|
||||
"models": ["gpt-4o", "gpt-4o-mini"],
|
||||
"required_keys": ["AZURE_OPENAI_ENDPOINT", "AZURE_OPENAI_DEPLOYMENT_NAME"]
|
||||
},
|
||||
"aws_bedrock": {
|
||||
"name": "AWS Bedrock",
|
||||
"description": "Connect to LLMs via AWS Bedrock",
|
||||
"models": ["us.anthropic.claude-3-7-sonnet-20250219-v1:0"],
|
||||
"required_keys": ["AWS_PROFILE"]
|
||||
},
|
||||
"xai": {
|
||||
"name": "Xai",
|
||||
"description": "Lorem ipsum",
|
||||
"models": ["grok-3"],
|
||||
"required_keys": ["XAI_API_KEY"]
|
||||
},
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
use super::utils::verify_secret_key;
|
||||
use chrono::{DateTime, Datelike};
|
||||
use chrono::DateTime;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -260,55 +260,6 @@ async fn get_session_insights(
|
||||
Ok(Json(insights))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/sessions/activity-heatmap",
|
||||
responses(
|
||||
(status = 200, description = "Activity heatmap data", body = [ActivityHeatmapCell]),
|
||||
(status = 401, description = "Unauthorized - Invalid or missing API key"),
|
||||
(status = 500, description = "Internal server error")
|
||||
),
|
||||
security(("api_key" = [])),
|
||||
tag = "Session Management"
|
||||
)]
|
||||
async fn get_activity_heatmap(
|
||||
State(state): State<Arc<AppState>>,
|
||||
headers: HeaderMap,
|
||||
) -> Result<Json<Vec<ActivityHeatmapCell>>, StatusCode> {
|
||||
verify_secret_key(&headers, &state)?;
|
||||
|
||||
let sessions = get_valid_sorted_sessions(SortOrder::Descending)
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
|
||||
// Only sessions with a description
|
||||
let sessions: Vec<SessionInfo> = sessions
|
||||
.into_iter()
|
||||
.filter(|session| !session.metadata.description.is_empty())
|
||||
.collect();
|
||||
|
||||
// Map: (week, day) -> count
|
||||
let mut heatmap: std::collections::HashMap<(usize, usize), usize> =
|
||||
std::collections::HashMap::new();
|
||||
|
||||
for session in &sessions {
|
||||
if let Ok(date) =
|
||||
chrono::NaiveDateTime::parse_from_str(&session.modified, "%Y-%m-%d %H:%M:%S UTC")
|
||||
{
|
||||
let date = date.date();
|
||||
let week = date.iso_week().week() as usize - 1; // 0-based week
|
||||
let day = date.weekday().num_days_from_sunday() as usize; // 0=Sun, 6=Sat
|
||||
*heatmap.entry((week, day)).or_insert(0) += 1;
|
||||
}
|
||||
}
|
||||
|
||||
let mut result = Vec::new();
|
||||
for ((week, day), count) in heatmap {
|
||||
result.push(ActivityHeatmapCell { week, day, count });
|
||||
}
|
||||
|
||||
Ok(Json(result))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
put,
|
||||
path = "/sessions/{session_id}/metadata",
|
||||
@@ -365,7 +316,6 @@ pub fn routes(state: Arc<AppState>) -> Router {
|
||||
.route("/sessions", get(list_sessions))
|
||||
.route("/sessions/{session_id}", get(get_session_history))
|
||||
.route("/sessions/insights", get(get_session_insights))
|
||||
.route("/sessions/activity-heatmap", get(get_activity_heatmap))
|
||||
.route(
|
||||
"/sessions/{session_id}/metadata",
|
||||
put(update_session_metadata),
|
||||
|
||||
Reference in New Issue
Block a user