[codex] add roles to realtime append text (#27936)

## Summary

Add an explicit `user` or `developer` role to
`thread/realtime/appendText` and propagate it through the realtime input
queue into `conversation.item.create`. Older JSON clients that omit the
field continue to default to `user`.

This lets app-provided context such as memory retain developer authority
without bypassing app-server through a renderer-owned data channel. The
app-server schemas, API documentation, and focused protocol and
websocket coverage are updated with the new contract.

The Codex Apps consumer is tracked in
[openai/openai#1025261](https://github.com/openai/openai/pull/1025261).
This commit is contained in:
Alex Gamble
2026-06-12 15:05:37 -07:00
committed by GitHub
parent 9915d34684
commit 216dee1189
18 changed files with 176 additions and 50 deletions
@@ -1,3 +1,4 @@
use codex_protocol::protocol::ConversationTextRole;
use codex_protocol::protocol::RealtimeAudioFrame as CoreRealtimeAudioFrame;
use codex_protocol::protocol::RealtimeConversationArchitecture;
use codex_protocol::protocol::RealtimeConversationVersion;
@@ -135,6 +136,8 @@ pub struct ThreadRealtimeAppendAudioResponse {}
pub struct ThreadRealtimeAppendTextParams {
pub thread_id: String,
pub text: String,
#[serde(default)]
pub role: ConversationTextRole,
}
/// EXPERIMENTAL - response for appending realtime text input.
@@ -27,6 +27,7 @@ use codex_protocol::permissions::FileSystemSandboxEntry as CoreFileSystemSandbox
use codex_protocol::permissions::FileSystemSpecialPath as CoreFileSystemSpecialPath;
use codex_protocol::protocol::AgentStatus as CoreAgentStatus;
use codex_protocol::protocol::AskForApproval as CoreAskForApproval;
use codex_protocol::protocol::ConversationTextRole;
use codex_protocol::protocol::GranularApprovalConfig as CoreGranularApprovalConfig;
use codex_protocol::protocol::NetworkAccess as CoreNetworkAccess;
use codex_protocol::request_permissions::RequestPermissionProfile as CoreRequestPermissionProfile;
@@ -3862,3 +3863,21 @@ fn turn_start_params_reject_relative_environment_cwd() {
"unexpected error: {err}"
);
}
#[test]
fn realtime_append_text_defaults_role_to_user() {
let params = serde_json::from_value::<ThreadRealtimeAppendTextParams>(json!({
"threadId": "thread_123",
"text": "hello",
}))
.expect("params should deserialize");
assert_eq!(
params,
ThreadRealtimeAppendTextParams {
thread_id: "thread_123".to_string(),
text: "hello".to_string(),
role: ConversationTextRole::User,
}
);
}