Skip to content

[codex] exec-server: stream files in chunks#28354

Merged
pakrym-oai merged 20 commits into
mainfrom
pakrym/fs-read-chunks-full-ci
Jun 16, 2026
Merged

[codex] exec-server: stream files in chunks#28354
pakrym-oai merged 20 commits into
mainfrom
pakrym/fs-read-chunks-full-ci

Conversation

@pakrym-oai

@pakrym-oai pakrym-oai commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Why

fs/readFile buffers the entire file in one response, which makes large remote reads expensive and prevents callers from applying backpressure. We need an opt-in streaming path with bounded block sizes while preserving the existing single-call API for small and sandboxed reads.

What changed

  • Add ExecServerClient::stream, returning a named FileReadStream that implements futures::Stream and yields immutable 1 MiB byte blocks.
  • Add internal fs/open, fs/readBlock, and fs/close RPCs. fs/readBlock accepts an explicit offset and length.
  • Keep unsandboxed files open between block reads, cap open handles per connection, and clean them up on EOF, error, stream drop, explicit close, or connection shutdown.
  • Reject platform-sandboxed streaming opens instead of turning the one-shot sandbox helper into a persistent server. Existing fs/readFile behavior is unchanged.

Testing

  • just test -p codex-exec-server
  • Integration coverage for 1 MiB chunking, exact block-boundary EOF, sandbox rejection, and continued reads from the opened file after path replacement.
  • Handle-manager coverage for non-sequential offsets, variable block lengths, the 128-handle limit, and capacity release after close.

@pakrym-oai
pakrym-oai marked this pull request as ready for review June 15, 2026 18:08
@pakrym-oai

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 741b2b9213

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread codex-rs/exec-server/src/local_file_system.rs Outdated
Comment thread codex-rs/exec-server/src/client.rs Outdated
@pakrym-oai

Copy link
Copy Markdown
Contributor Author

@codex review this

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5ab7aba16a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread codex-rs/exec-server/src/client.rs Outdated
Comment thread codex-rs/exec-server/src/client.rs Outdated
@pakrym-oai
pakrym-oai requested a review from a team as a code owner June 15, 2026 19:44
@pakrym-oai

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown
Contributor

Codex Review: Didn't find any major issues. Breezy!

Reviewed commit: 701738caec

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@jif-oai jif-oai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to discuss those points but I like the direction that this took

) -> FileSystemResult<tokio::fs::File> {
reject_sandbox_context(sandbox)?;
let path = path.to_abs_path()?;
if !tokio::fs::metadata(path.as_path()).await?.is_file() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess you know it but this is still Windows unsafe right?
PathUri round-trips \\.\pipe\..., metadata() itself opens the path with default QOS, and is_file() does not prove FILE_TYPE_DISK
Thsi exposed to named-pipe impersonation etc

format!("file read handle `{handle_id}` already exists"),
));
}
if handles.len() >= MAX_OPEN_FILE_READS {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ultra nit: the 128-entries cap doesn’t bound memory because handleId is an unrestricted caller string. stdio has no message-size cap so a gigantic id remain resident
Since the client is using uuids anyway, we could simply enforce >= 16 bytes or something like this (even 32 if we want a margin)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

) -> FileSystemResult<tokio::fs::File> {
reject_sandbox_context(sandbox)?;
let path = path.to_abs_path()?;
if !tokio::fs::metadata(path.as_path()).await?.is_file() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also think there is something slightly racy here. metadata() validates one path target, then File::open() resolves it again but after an await

I don't think this is a big deal but it would be cleaner to open nonblocking and validated the opened descriptor instead of validating the path name (for unix ofc)

…-full-ci

# Conflicts:
#	codex-rs/app-server/tests/suite/v2/external_agent_config.rs
@pakrym-oai
pakrym-oai merged commit a4711b8 into main Jun 16, 2026
61 of 74 checks passed
@pakrym-oai
pakrym-oai deleted the pakrym/fs-read-chunks-full-ci branch June 16, 2026 16:51
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 16, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants