182 lines
5.2 KiB
Rust
182 lines
5.2 KiB
Rust
use actix_web::{HttpResponse, Result, web};
|
|
use service::error::AppError;
|
|
use session::Session;
|
|
use uuid::Uuid;
|
|
|
|
use crate::ApiResponse;
|
|
use crate::error::ApiError;
|
|
|
|
use super::types::{ConversationListQuery, ConversationResponse, CreateConversationParams};
|
|
|
|
fn get_user_id(session: &Session) -> Result<Uuid, ApiError> {
|
|
session
|
|
.user()
|
|
.ok_or_else(|| ApiError::from(AppError::Unauthorized))
|
|
}
|
|
|
|
#[utoipa::path(
|
|
post,
|
|
path = "/api/ai/conversations",
|
|
operation_id = "ai_conversation_create",
|
|
request_body = CreateConversationParams,
|
|
responses(
|
|
(status = 200, description = "Conversation created", body = ApiResponse<ConversationResponse>),
|
|
(status = 401, description = "Unauthorized"),
|
|
),
|
|
tag = "AI Chat"
|
|
)]
|
|
pub async fn conversation_create(
|
|
service: web::Data<service::AppService>,
|
|
session: Session,
|
|
params: web::Json<CreateConversationParams>,
|
|
) -> Result<HttpResponse, ApiError> {
|
|
let user_id = get_user_id(&session)?;
|
|
let model = params.model.clone().unwrap_or_else(|| "gpt-4".to_string());
|
|
|
|
let conversation = service
|
|
.create_conversation(
|
|
user_id,
|
|
params.project_id,
|
|
params.title.clone(),
|
|
model,
|
|
params.model_config.clone(),
|
|
params.access_visibility.clone(),
|
|
params.can_ask.clone(),
|
|
params.model_uid,
|
|
params.model_name.clone(),
|
|
)
|
|
.await?;
|
|
|
|
let resp = ConversationResponse::from(conversation);
|
|
Ok(ApiResponse::ok(resp).to_response())
|
|
}
|
|
|
|
#[utoipa::path(
|
|
get,
|
|
path = "/api/ai/conversations",
|
|
operation_id = "ai_conversation_list",
|
|
params(
|
|
("project_id" = Option<Uuid>, Query, description = "Filter by project"),
|
|
("q" = Option<String>, Query, description = "Search query (title)"),
|
|
),
|
|
responses(
|
|
(status = 200, description = "List of conversations", body = ApiResponse<Vec<ConversationResponse>>),
|
|
(status = 401, description = "Unauthorized"),
|
|
),
|
|
tag = "AI Chat"
|
|
)]
|
|
pub async fn conversation_list(
|
|
service: web::Data<service::AppService>,
|
|
session: Session,
|
|
query: web::Query<ConversationListQuery>,
|
|
) -> Result<HttpResponse, ApiError> {
|
|
let user_id = get_user_id(&session)?;
|
|
|
|
let convs = service
|
|
.list_conversations(user_id, query.project_id, 50, query.q.clone())
|
|
.await?;
|
|
|
|
let resp: Vec<ConversationResponse> =
|
|
convs.into_iter().map(ConversationResponse::from).collect();
|
|
|
|
Ok(ApiResponse::ok(resp).to_response())
|
|
}
|
|
|
|
#[utoipa::path(
|
|
get,
|
|
path = "/api/ai/conversations/{conversation_id}",
|
|
operation_id = "ai_conversation_get",
|
|
params(
|
|
("conversation_id" = Uuid, Path, description = "Conversation ID"),
|
|
),
|
|
responses(
|
|
(status = 200, description = "Get conversation", body = ApiResponse<ConversationResponse>),
|
|
(status = 404, description = "Not found"),
|
|
),
|
|
tag = "AI Chat"
|
|
)]
|
|
pub async fn conversation_get(
|
|
service: web::Data<service::AppService>,
|
|
session: Session,
|
|
path: web::Path<Uuid>,
|
|
) -> Result<HttpResponse, ApiError> {
|
|
let user_id = get_user_id(&session)?;
|
|
let conversation_id = path.into_inner();
|
|
|
|
let c = service
|
|
.find_conversation_owned(conversation_id, user_id)
|
|
.await?;
|
|
|
|
let resp = ConversationResponse::from(c);
|
|
Ok(ApiResponse::ok(resp).to_response())
|
|
}
|
|
|
|
#[utoipa::path(
|
|
patch,
|
|
path = "/api/ai/conversations/{conversation_id}",
|
|
operation_id = "ai_conversation_update",
|
|
params(
|
|
("conversation_id" = Uuid, Path, description = "Conversation ID"),
|
|
),
|
|
request_body = super::types::UpdateConversationParams,
|
|
responses(
|
|
(status = 200, description = "Conversation updated"),
|
|
(status = 404, description = "Not found"),
|
|
),
|
|
tag = "AI Chat"
|
|
)]
|
|
pub async fn conversation_update(
|
|
service: web::Data<service::AppService>,
|
|
session: Session,
|
|
path: web::Path<Uuid>,
|
|
params: web::Json<super::types::UpdateConversationParams>,
|
|
) -> Result<HttpResponse, ApiError> {
|
|
let user_id = get_user_id(&session)?;
|
|
let conversation_id = path.into_inner();
|
|
|
|
service
|
|
.update_conversation(
|
|
conversation_id,
|
|
user_id,
|
|
params.title.clone(),
|
|
params.model.clone(),
|
|
params.model_config.clone(),
|
|
params.status.clone(),
|
|
params.access_visibility.clone(),
|
|
params.can_ask.clone(),
|
|
params.model_uid,
|
|
params.model_name.clone(),
|
|
)
|
|
.await?;
|
|
|
|
Ok(crate::api_success())
|
|
}
|
|
|
|
#[utoipa::path(
|
|
delete,
|
|
path = "/api/ai/conversations/{conversation_id}",
|
|
operation_id = "ai_conversation_delete",
|
|
params(
|
|
("conversation_id" = Uuid, Path, description = "Conversation ID"),
|
|
),
|
|
responses(
|
|
(status = 200, description = "Conversation deleted"),
|
|
(status = 404, description = "Not found"),
|
|
),
|
|
tag = "AI Chat"
|
|
)]
|
|
pub async fn conversation_delete(
|
|
service: web::Data<service::AppService>,
|
|
session: Session,
|
|
path: web::Path<Uuid>,
|
|
) -> Result<HttpResponse, ApiError> {
|
|
let user_id = get_user_id(&session)?;
|
|
let conversation_id = path.into_inner();
|
|
|
|
service
|
|
.delete_conversation(conversation_id, user_id)
|
|
.await?;
|
|
|
|
Ok(crate::api_success())
|
|
}
|