app-server: add v2 filesystem APIs (#14245)

Add a protocol-level filesystem surface to the v2 app-server so Codex
clients can read and write files, inspect directories, and subscribe to
path changes without relying on host-specific helpers.

High-level changes:
- define the new v2 fs/readFile, fs/writeFile, fs/createDirectory,
fs/getMetadata, fs/readDirectory, fs/remove, fs/copy RPCs
- implement the app-server handlers, including absolute-path validation,
base64 file payloads, recursive copy/remove semantics
- document the API, regenerate protocol schemas/types, and add
end-to-end tests for filesystem operations, copy edge cases

Testing plan:
- validate protocol serialization and generated schema output for the
new fs request, response, and notification types
- run app-server integration coverage for file and directory CRUD paths,
metadata/readDirectory responses, copy failure modes, and absolute-path
validation
This commit is contained in:
Ruslan Nigmatullin
2026-03-13 14:42:20 -07:00
committed by GitHub
parent 36dfb84427
commit f8f82bfc2b
46 changed files with 3391 additions and 8 deletions

View File

@@ -25,6 +25,13 @@ use codex_app_server_protocol::ConfigReadParams;
use codex_app_server_protocol::ConfigValueWriteParams;
use codex_app_server_protocol::ExperimentalFeatureListParams;
use codex_app_server_protocol::FeedbackUploadParams;
use codex_app_server_protocol::FsCopyParams;
use codex_app_server_protocol::FsCreateDirectoryParams;
use codex_app_server_protocol::FsGetMetadataParams;
use codex_app_server_protocol::FsReadDirectoryParams;
use codex_app_server_protocol::FsReadFileParams;
use codex_app_server_protocol::FsRemoveParams;
use codex_app_server_protocol::FsWriteFileParams;
use codex_app_server_protocol::GetAccountParams;
use codex_app_server_protocol::GetAuthStatusParams;
use codex_app_server_protocol::GetConversationSummaryParams;
@@ -709,6 +716,56 @@ impl McpProcess {
self.send_request("config/batchWrite", params).await
}
pub async fn send_fs_read_file_request(
&mut self,
params: FsReadFileParams,
) -> anyhow::Result<i64> {
let params = Some(serde_json::to_value(params)?);
self.send_request("fs/readFile", params).await
}
pub async fn send_fs_write_file_request(
&mut self,
params: FsWriteFileParams,
) -> anyhow::Result<i64> {
let params = Some(serde_json::to_value(params)?);
self.send_request("fs/writeFile", params).await
}
pub async fn send_fs_create_directory_request(
&mut self,
params: FsCreateDirectoryParams,
) -> anyhow::Result<i64> {
let params = Some(serde_json::to_value(params)?);
self.send_request("fs/createDirectory", params).await
}
pub async fn send_fs_get_metadata_request(
&mut self,
params: FsGetMetadataParams,
) -> anyhow::Result<i64> {
let params = Some(serde_json::to_value(params)?);
self.send_request("fs/getMetadata", params).await
}
pub async fn send_fs_read_directory_request(
&mut self,
params: FsReadDirectoryParams,
) -> anyhow::Result<i64> {
let params = Some(serde_json::to_value(params)?);
self.send_request("fs/readDirectory", params).await
}
pub async fn send_fs_remove_request(&mut self, params: FsRemoveParams) -> anyhow::Result<i64> {
let params = Some(serde_json::to_value(params)?);
self.send_request("fs/remove", params).await
}
pub async fn send_fs_copy_request(&mut self, params: FsCopyParams) -> anyhow::Result<i64> {
let params = Some(serde_json::to_value(params)?);
self.send_request("fs/copy", params).await
}
/// Send an `account/logout` JSON-RPC request.
pub async fn send_logout_account_request(&mut self) -> anyhow::Result<i64> {
self.send_request("account/logout", None).await