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 crate::require_live_session::require_live_session(server, &req.session_id).await?;
21
22 let sid = req
23 .session_id
24 .parse::<uuid::Uuid>()
25 .map_err(|_| Status::invalid_argument("Invalid session ID"))?;
26 server.session_mgr().touch_session(&sid);
27
28 let engine = server.engine();
29
30 let ws = engine
32 .workspace_manager()
33 .get_workspace(&sid)
34 .ok_or_else(|| Status::not_found("Workspace not found for session"))?;
35
36 let (_repo_id, git_repo) = engine
38 .get_repo(&session.codebase)
39 .await
40 .map_err(|e| Status::internal(format!("Repo error: {e}")))?;
41
42 let result = ws
43 .read_file(&req.path, &git_repo)
44 .map_err(|e| Status::not_found(format!("File not found: {e}")))?;
45
46 ws.mark_read(&req.path);
50
51 info!(
52 session_id = %req.session_id,
53 path = %req.path,
54 modified = result.modified_in_session,
55 "FILE_READ: served"
56 );
57
58 Ok(Response::new(FileReadResponse {
59 content: result.content,
60 hash: result.hash,
61 modified_in_session: result.modified_in_session,
62 }))
63}