/
alexefan136
/
flowstack
Обзор
Документация
Войти
/
alexefan136
/
flowstack
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
core/gateway/src/proxy/agents.rs
170 строк
6 KB
Alexander Efanov
upd fix
31 июл 2026, 19:17
31 июл 2026, 19:17
d146d86
Код
Авторство
О чём код?
//! Proxy handlers для агентов (Gateway → Engine). //! //! Использует generic [`proxy_to_engine`] из [`super::forward`]: //! - Автоопределение SSE streaming (критично для `POST /agents/{id}/run`) //! - Inject `X-User-ID` / `X-Workspace-ID` из AuthContext //! - Circuit breaker + error handling //! //! ⚠️ Порядок роутов в main.rs: `/types`, `/stats` ДО `/{agent_id}` //! (статические пути до динамических). use axum::{ body::Bytes, extract::{Path, State}, http::{HeaderMap, Method}, response::Response, }; use tracing::info; use super::forward::{ProxyState, proxy_to_engine}; use crate::auth::OptionalAuth; // ============================================================================ // COLLECTION ENDPOINTS // ============================================================================ /// GET /api/v1/agents — список агентов pub async fn proxy_agents_list( State(state): State<ProxyState>, OptionalAuth(auth): OptionalAuth, headers: HeaderMap, ) -> Response { proxy_to_engine(&state, Method::GET, "/api/v1/agents", auth, headers, None).await } /// POST /api/v1/agents — создать агента pub async fn proxy_agents_create( State(state): State<ProxyState>, OptionalAuth(auth): OptionalAuth, headers: HeaderMap, body: Bytes, ) -> Response { proxy_to_engine( &state, Method::POST, "/api/v1/agents", auth, headers, Some(body), ) .await } /// GET /api/v1/agents/types — список типов агентов (для UI) /// /// ⚠️ Должен быть зарегистрирован ДО `/{agent_id}` в main.rs. pub async fn proxy_agents_types( State(state): State<ProxyState>, OptionalAuth(auth): OptionalAuth, headers: HeaderMap, ) -> Response { proxy_to_engine( &state, Method::GET, "/api/v1/agents/types", auth, headers, None, ) .await } /// GET /api/v1/agents/stats — агрегированная статистика по агентам /// /// ⚠️ Должен быть зарегистрирован ДО `/{agent_id}` в main.rs. pub async fn proxy_agents_stats( State(state): State<ProxyState>, OptionalAuth(auth): OptionalAuth, headers: HeaderMap, ) -> Response { proxy_to_engine( &state, Method::GET, "/api/v1/agents/stats", auth, headers, None, ) .await } // ============================================================================ // ITEM ENDPOINTS // ============================================================================ /// GET /api/v1/agents/{agent_id} — получить агента pub async fn proxy_agents_get( State(state): State<ProxyState>, Path(agent_id): Path<String>, OptionalAuth(auth): OptionalAuth, headers: HeaderMap, ) -> Response { let path = format!("/api/v1/agents/{}", agent_id); proxy_to_engine(&state, Method::GET, &path, auth, headers, None).await } /// PATCH /api/v1/agents/{agent_id} — обновить агента pub async fn proxy_agents_update( State(state): State<ProxyState>, Path(agent_id): Path<String>, OptionalAuth(auth): OptionalAuth, headers: HeaderMap, body: Bytes, ) -> Response { let path = format!("/api/v1/agents/{}", agent_id); proxy_to_engine(&state, Method::PATCH, &path, auth, headers, Some(body)).await } /// DELETE /api/v1/agents/{agent_id} — удалить агента pub async fn proxy_agents_delete( State(state): State<ProxyState>, Path(agent_id): Path<String>, OptionalAuth(auth): OptionalAuth, headers: HeaderMap, ) -> Response { let path = format!("/api/v1/agents/{}", agent_id); proxy_to_engine(&state, Method::DELETE, &path, auth, headers, None).await } /// GET /api/v1/agents/{agent_id}/stats — детальная статистика агента pub async fn proxy_agents_get_stats( State(state): State<ProxyState>, Path(agent_id): Path<String>, OptionalAuth(auth): OptionalAuth, headers: HeaderMap, ) -> Response { let path = format!("/api/v1/agents/{}/stats", agent_id); proxy_to_engine(&state, Method::GET, &path, auth, headers, None).await } // ============================================================================ // ACTION ENDPOINTS // ============================================================================ /// POST /api/v1/agents/{agent_id}/run — запустить агента (sync или SSE) /// /// Engine возвращает SSE (`text/event-stream`) при `stream=true` — /// `proxy_to_engine` автоматически определяет это и стримит ответ /// (события: agent_start, reasoning, agent_message, tool_call, agent_done). pub async fn proxy_agents_run( State(state): State<ProxyState>, Path(agent_id): Path<String>, OptionalAuth(auth): OptionalAuth, headers: HeaderMap, body: Bytes, ) -> Response { info!(agent_id = %agent_id, body_size = body.len(), "proxy_agents_run"); let path = format!("/api/v1/agents/{}/run", agent_id); proxy_to_engine(&state, Method::POST, &path, auth, headers, Some(body)).await } /// POST /api/v1/agents/{agent_id}/stop — остановить агента (сброс статуса) pub async fn proxy_agents_stop( State(state): State<ProxyState>, Path(agent_id): Path<String>, OptionalAuth(auth): OptionalAuth, headers: HeaderMap, ) -> Response { let path = format!("/api/v1/agents/{}/stop", agent_id); proxy_to_engine(&state, Method::POST, &path, auth, headers, None).await }