mirror of
https://github.com/openai/codex.git
synced 2026-10-19 17:28:46 +00:00
core: support extension-owned turn items (#31283)
## Description
This PR adds a `codex-extension-items` crate for extension-owned
`TurnItem` schemas, and updates standalone image generation to start
using it via `TurnItem::Extension`.
This gives us a way to prevent Core from having to be aware of all
extension items. App-server still exposes the existing public
`ThreadItem::ImageGeneration` shape, now by wrapping the same shared
`image_generation::ImageGenerationItem` type.
The new `codex-extension-items` crate is necessary because the image gen
extension item is used by:
- `codex-image-generation-extension`, which produces it.
- `codex-tools / core`, which carry it generically.
- `codex-protocol`, which serializes it into lifecycle events and
rollouts.
- `app-server protocol`, which wraps it in public
`ThreadItem::ImageGeneration`
```
extension implementation
↓
codex-extension-items
↓
protocol / tools / app-server
```
We keep the hosted Responses API image generation as
`TurnItem::ImageGeneration` because core still owns its persistence and
legacy fanout.
### Before
Standalone image generation is implemented as an extension, but its item
representation previously lived in the core protocol. This sets the
precedent that core is aware of all extension items, which would be good
to avoid.
```
image-gen extension
→ constructs codex_protocol::ImageGenerationItem
→ emits ExtensionTurnItem::ImageGeneration
→ core matches ImageGeneration specially
→ protocol stores TurnItem::ImageGeneration
```
### After
```
image-gen extension
→ constructs extension-owned ImageGenerationItem
→ emits generic ExtensionItem
→ core transports/persists it generically
→ app-server wraps ImageGenerationItem as ThreadItem::ImageGeneration
```
Future extension items can have typed app-server APIs without adding a
new `TurnItem` variant, `ExtensionTurnItem` variant, or core emitter
match arm.
## What changed
- Added `codex-extension-items` with the closed `ExtensionItem` enum and
shared `image_generation::ImageGenerationItem` schema.
- Added generic `TurnItem::Extension(ExtensionItem)` and
`ExtensionTurnItem::Extension { item, legacy_events }` paths.
- Updated standalone image generation to emit a typed extension item and
provide its existing legacy `ImageGenerationBegin` /
`ImageGenerationEnd` events explicitly.
- Kept canonical lifecycle ordering: core emits `ItemStarted` /
`ItemCompleted` before extension-provided legacy events.
## Follow-up
Standalone web search still uses its typed special-case path. Migrating
it later would let `ExtensionTurnItem` collapse into a single
extension-item struct.
This commit is contained in:
@@ -20,6 +20,7 @@ use crate::protocol::SubAgentActivityKind;
|
||||
use crate::user_input::ByteRange;
|
||||
use crate::user_input::TextElement;
|
||||
use crate::user_input::UserInput;
|
||||
use codex_extension_items::ExtensionItem;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use codex_utils_path_uri::PathUri;
|
||||
use quick_xml::de::from_str as from_xml_str;
|
||||
@@ -49,6 +50,15 @@ pub enum TurnItem {
|
||||
WebSearch(WebSearchItem),
|
||||
ImageView(ImageViewItem),
|
||||
Sleep(SleepItem),
|
||||
/// Item whose schema and lifecycle details are owned by an extension.
|
||||
///
|
||||
/// Standalone image generation uses this path. App-server wraps the same
|
||||
/// typed item in its public image-generation variant.
|
||||
Extension(ExtensionItem),
|
||||
/// Hosted Responses API image-generation item handled directly by core.
|
||||
///
|
||||
/// This remains separate from [`Self::Extension`] because core still owns
|
||||
/// hosted image persistence and legacy-event fanout.
|
||||
ImageGeneration(ImageGenerationItem),
|
||||
FileChange(FileChangeItem),
|
||||
McpToolCall(McpToolCallItem),
|
||||
@@ -605,6 +615,7 @@ impl TurnItem {
|
||||
TurnItem::WebSearch(item) => item.id.clone(),
|
||||
TurnItem::ImageView(item) => item.id.clone(),
|
||||
TurnItem::Sleep(item) => item.id.clone(),
|
||||
TurnItem::Extension(item) => item.id().to_string(),
|
||||
TurnItem::ImageGeneration(item) => item.id.clone(),
|
||||
TurnItem::FileChange(item) => item.id.clone(),
|
||||
TurnItem::McpToolCall(item) => item.id.clone(),
|
||||
|
||||
@@ -487,6 +487,7 @@ impl TurnItem {
|
||||
})]
|
||||
}
|
||||
TurnItem::Sleep(_) => Vec::new(),
|
||||
TurnItem::Extension(_) => Vec::new(),
|
||||
TurnItem::ImageGeneration(item) => vec![item.as_legacy_event()],
|
||||
TurnItem::FileChange(item) => item
|
||||
.as_legacy_end_event(String::new())
|
||||
|
||||
Reference in New Issue
Block a user