1use tonic::{Response, Status};
2use tracing::info;
3
4use crate::server::ProtocolServer;
5use crate::validation::validate_file_path;
6use crate::{FileReadRequest, FileReadResponse};
7
8pub async fn handle_file_read(
14 server: &ProtocolServer,
15 req: FileReadRequest,
16) -> Result<Response<FileReadResponse>, Status> {
17 validate_file_path(&req.path)?;
18
19 let session = server.validate_session(&req.session_id)?;
20
21 let sid = req
22 .session_id
23 .parse::<uuid::Uuid>()
24 .map_err(|_| Status::invalid_argument("Invalid session ID"))?;
25 server.session_mgr().touch_session(&sid);
26
27 let engine = server.engine();
28
29 let ws = engine
31 .workspace_manager()
32 .get_workspace(&sid)
33 .ok_or_else(|| Status::not_found("Workspace not found for session"))?;
34
35 let (_repo_id, git_repo) = engine
37 .get_repo(&session.codebase)
38 .await
39 .map_err(|e| Status::internal(format!("Repo error: {e}")))?;
40
41 let result = ws
42 .read_file(&req.path, &git_repo)
43 .map_err(|e| Status::not_found(format!("File not found: {e}")))?;
44
45 info!(
46 session_id = %req.session_id,
47 path = %req.path,
48 modified = result.modified_in_session,
49 "FILE_READ: served"
50 );
51
52 Ok(Response::new(FileReadResponse {
53 content: result.content,
54 hash: result.hash,
55 modified_in_session: result.modified_in_session,
56 }))
57}