feat: copy-file autocomplete (#2004)

* add repo file search endpoint and use for copy-file autocomplete

* address feedback and fix i18n errors

* remove unused i18n
This commit is contained in:
Gabriel Gordon-Hall
2026-01-13 17:34:54 +00:00
committed by GitHub
parent 5502a4cad6
commit cdfb081cf8
32 changed files with 296 additions and 241 deletions

View File

@@ -151,6 +151,7 @@ fn generate_types_content() -> String {
server::routes::task_attempts::workspace_summary::WorkspaceSummaryResponse::decl(),
services::services::filesystem::DirectoryEntry::decl(),
services::services::filesystem::DirectoryListResponse::decl(),
services::services::file_search::SearchMode::decl(),
services::services::config::Config::decl(),
services::services::config::NotificationConfig::decl(),
services::services::config::ThemeMode::decl(),

View File

@@ -21,7 +21,7 @@ use deployment::Deployment;
use futures_util::{SinkExt, StreamExt, TryStreamExt};
use serde::Deserialize;
use services::services::{
file_search_cache::SearchQuery, project::ProjectServiceError,
file_search::SearchQuery, project::ProjectServiceError,
remote_client::CreateRemoteProjectPayload,
};
use ts_rs::TS;

View File

@@ -1,13 +1,17 @@
use axum::{
Router,
extract::{Path, State},
extract::{Path, Query, State},
http::StatusCode,
response::Json as ResponseJson,
routing::{get, post},
};
use db::models::repo::{Repo, UpdateRepo};
use db::models::{
project::SearchResult,
repo::{Repo, UpdateRepo},
};
use deployment::Deployment;
use serde::Deserialize;
use services::services::git::GitBranch;
use services::services::{file_search::SearchQuery, git::GitBranch};
use ts_rs::TS;
use utils::response::ApiResponse;
use uuid::Uuid;
@@ -166,6 +170,42 @@ pub async fn open_repo_in_editor(
}
}
pub async fn search_repo(
State(deployment): State<DeploymentImpl>,
Path(repo_id): Path<Uuid>,
Query(search_query): Query<SearchQuery>,
) -> Result<ResponseJson<ApiResponse<Vec<SearchResult>>>, StatusCode> {
if search_query.q.trim().is_empty() {
return Ok(ResponseJson(ApiResponse::error(
"Query parameter 'q' is required and cannot be empty",
)));
}
let repo = match deployment
.repo()
.get_by_id(&deployment.db().pool, repo_id)
.await
{
Ok(repo) => repo,
Err(e) => {
tracing::error!("Failed to get repo {}: {}", repo_id, e);
return Err(StatusCode::NOT_FOUND);
}
};
match deployment
.file_search_cache()
.search_repo(&repo.path, &search_query.q, search_query.mode)
.await
{
Ok(results) => Ok(ResponseJson(ApiResponse::success(results))),
Err(e) => {
tracing::error!("Failed to search files in repo {}: {}", repo_id, e);
Err(StatusCode::INTERNAL_SERVER_ERROR)
}
}
}
pub fn router() -> Router<DeploymentImpl> {
Router::new()
.route("/repos", get(get_repos).post(register_repo))
@@ -173,5 +213,6 @@ pub fn router() -> Router<DeploymentImpl> {
.route("/repos/batch", post(get_repos_batch))
.route("/repos/{repo_id}", get(get_repo).put(update_repo))
.route("/repos/{repo_id}/branches", get(get_repo_branches))
.route("/repos/{repo_id}/search", get(search_repo))
.route("/repos/{repo_id}/open-editor", post(open_repo_in_editor))
}