Route image extension reads through turn environments v2 (#27498)

## Why

Image generation used `std::fs::read` for referenced image paths, which
did not support environment-backed filesystems or their sandbox context.

## What changed

- Expose optional turn environments to extension tool calls.
- Include each environment’s ID, working directory, filesystem, and
sandbox context.
- Read referenced images through the selected environment filesystem.
- Keep sandbox usage at the extension call site so extensions can choose
the appropriate access mode.
- Consolidate image request construction into one async function.
- Add coverage for successful environment reads and read failures.

## Validation

- `cargo check -p codex-image-generation-extension --tests`
- `just fmt`
- `just bazel-lock-update`
- `just bazel-lock-check`

`just test -p codex-image-generation-extension` could not complete
because the build exhausted available disk space.
This commit is contained in:
Won Park
2026-06-11 16:32:52 -07:00
committed by GitHub
parent b2cc01fc7c
commit 19ce6394af
14 changed files with 423 additions and 34 deletions
+1
View File
@@ -66,6 +66,7 @@ pub use tool_call::ConversationHistory;
pub use tool_call::ExtensionTurnItem;
pub use tool_call::NoopTurnItemEmitter;
pub use tool_call::ToolCall;
pub use tool_call::ToolEnvironment;
pub use tool_call::TurnItemEmissionFuture;
pub use tool_call::TurnItemEmitter;
pub use tool_config::ShellCommandBackendConfig;
+18
View File
@@ -1,9 +1,12 @@
use crate::FunctionCallError;
use crate::ToolName;
use crate::ToolPayload;
use codex_file_system::ExecutorFileSystem;
use codex_file_system::FileSystemSandboxContext;
use codex_protocol::items::ImageGenerationItem;
use codex_protocol::items::WebSearchItem;
use codex_protocol::models::ResponseItem;
use codex_utils_absolute_path::AbsolutePathBuf;
use codex_utils_output_truncation::TruncationPolicy;
use std::future::Future;
use std::pin::Pin;
@@ -49,6 +52,19 @@ pub trait TurnItemEmitter: Send + Sync {
fn emit_completed<'a>(&'a self, item: ExtensionTurnItem) -> TurnItemEmissionFuture<'a>;
}
/// Host-owned turn environment summary visible to extension tools.
#[derive(Clone)]
pub struct ToolEnvironment {
/// Stable host environment id used to route executor-scoped capabilities.
pub environment_id: String,
/// Effective working directory for this turn in the environment.
pub cwd: AbsolutePathBuf,
/// Filesystem implementation for this environment.
pub file_system: Arc<dyn ExecutorFileSystem>,
/// Sandbox context to use for filesystem operations.
pub file_system_sandbox_context: FileSystemSandboxContext,
}
/// Turn-item emitter used when a caller does not expose visible item emission.
#[derive(Debug, Default, Clone, Copy)]
pub struct NoopTurnItemEmitter;
@@ -72,6 +88,7 @@ pub struct ToolCall {
pub truncation_policy: TruncationPolicy,
pub conversation_history: ConversationHistory,
pub turn_item_emitter: Arc<dyn TurnItemEmitter>,
pub environments: Vec<ToolEnvironment>,
pub payload: ToolPayload,
}
@@ -85,6 +102,7 @@ impl std::fmt::Debug for ToolCall {
.field("truncation_policy", &self.truncation_policy)
.field("conversation_history", &self.conversation_history)
.field("turn_item_emitter", &"<host turn item emitter>")
.field("environment_count", &self.environments.len())
.field("payload", &self.payload)
.finish()
}