mirror of
https://github.com/openai/codex.git
synced 2026-04-28 08:34:54 +00:00
Register agent tasks behind use_agent_identity (#17387)
## Summary Stack PR3 for feature-gated agent identity support. This PR adds per-thread agent task registration behind `features.use_agent_identity`. Tasks are minted on the first real user turn and cached in thread runtime state for later turns. ## Stack - PR1: https://github.com/openai/codex/pull/17385 - add `features.use_agent_identity` - PR2: https://github.com/openai/codex/pull/17386 - register agent identities when enabled - PR3: https://github.com/openai/codex/pull/17387 - this PR, original task registration slice - PR3.1: https://github.com/openai/codex/pull/17978 - persist and prewarm registered tasks per thread - PR4: https://github.com/openai/codex/pull/17980 - use `AgentAssertion` downstream when enabled ## Validation Covered as part of the local stack validation pass: - `just fmt` - `cargo test -p codex-core --lib agent_identity` - `cargo test -p codex-core --lib agent_assertion` - `cargo test -p codex-core --lib websocket_agent_task` - `cargo test -p codex-api api_bridge` - `cargo build -p codex-cli --bin codex` ## Notes The full local app-server E2E path is still being debugged after PR creation. The current branch stack is directionally ready for review while that follow-up continues.
This commit is contained in:
@@ -15,6 +15,7 @@ use codex_protocol::protocol::ConversationStartTransport;
|
||||
use codex_protocol::protocol::ConversationTextParams;
|
||||
use codex_protocol::protocol::ErrorEvent;
|
||||
use codex_protocol::protocol::EventMsg;
|
||||
use codex_protocol::protocol::GitInfo;
|
||||
use codex_protocol::protocol::InitialHistory;
|
||||
use codex_protocol::protocol::Op;
|
||||
use codex_protocol::protocol::RealtimeAudioFrame;
|
||||
@@ -24,7 +25,11 @@ use codex_protocol::protocol::RealtimeEvent;
|
||||
use codex_protocol::protocol::RealtimeOutputModality;
|
||||
use codex_protocol::protocol::RealtimeVoice;
|
||||
use codex_protocol::protocol::RolloutItem;
|
||||
use codex_protocol::protocol::RolloutLine;
|
||||
use codex_protocol::protocol::SessionMeta;
|
||||
use codex_protocol::protocol::SessionMetaLine;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use codex_protocol::protocol::UserMessageEvent;
|
||||
use codex_protocol::user_input::UserInput;
|
||||
use codex_utils_output_truncation::approx_token_count;
|
||||
use core_test_support::responses;
|
||||
@@ -65,6 +70,7 @@ const MEMORY_PROMPT_PHRASE: &str =
|
||||
"You have access to a memory folder with guidance from prior runs.";
|
||||
const REALTIME_CONVERSATION_TEST_SUBPROCESS_ENV_VAR: &str =
|
||||
"CODEX_REALTIME_CONVERSATION_TEST_SUBPROCESS";
|
||||
const WEBSOCKET_REQUEST_TIMEOUT: Duration = Duration::from_secs(30);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct RealtimeCallRequestCapture {
|
||||
@@ -141,7 +147,7 @@ async fn wait_for_matching_websocket_request<F>(
|
||||
where
|
||||
F: Fn(&core_test_support::responses::WebSocketRequest) -> bool,
|
||||
{
|
||||
let deadline = tokio::time::Instant::now() + Duration::from_secs(10);
|
||||
let deadline = tokio::time::Instant::now() + WEBSOCKET_REQUEST_TIMEOUT;
|
||||
loop {
|
||||
if let Some(request) = server
|
||||
.connections()
|
||||
@@ -196,16 +202,18 @@ async fn seed_recent_thread(
|
||||
let db = test.codex.state_db().context("state db enabled")?;
|
||||
let thread_id = ThreadId::new();
|
||||
let updated_at = Utc::now();
|
||||
let rollout_path = test
|
||||
let rollout_dir = test
|
||||
.codex_home_path()
|
||||
.join(format!("rollout-{thread_id}.jsonl"));
|
||||
// This helper seeds SQLite metadata directly. Local listing drops stale metadata rows whose
|
||||
// rollout path no longer exists, so create the placeholder path that the test metadata points
|
||||
// at without exercising rollout writing in this realtime-context test.
|
||||
std::fs::write(&rollout_path, "")?;
|
||||
.join("sessions")
|
||||
.join(updated_at.format("%Y/%m/%d").to_string());
|
||||
fs::create_dir_all(&rollout_dir)?;
|
||||
let rollout_path = rollout_dir.join(format!(
|
||||
"rollout-{}-{thread_id}.jsonl",
|
||||
updated_at.format("%Y-%m-%dT%H-%M-%S")
|
||||
));
|
||||
let mut metadata_builder = codex_state::ThreadMetadataBuilder::new(
|
||||
thread_id,
|
||||
rollout_path,
|
||||
rollout_path.clone(),
|
||||
updated_at,
|
||||
SessionSource::Cli,
|
||||
);
|
||||
@@ -215,6 +223,45 @@ async fn seed_recent_thread(
|
||||
let mut metadata = metadata_builder.build("test-provider");
|
||||
metadata.title = title.to_string();
|
||||
metadata.first_user_message = Some(first_user_message.to_string());
|
||||
|
||||
let timestamp = updated_at.to_rfc3339();
|
||||
let session_meta = RolloutLine {
|
||||
timestamp: timestamp.clone(),
|
||||
item: RolloutItem::SessionMeta(SessionMetaLine {
|
||||
meta: SessionMeta {
|
||||
id: thread_id,
|
||||
timestamp: timestamp.clone(),
|
||||
cwd: metadata.cwd.clone(),
|
||||
originator: "cli".to_string(),
|
||||
cli_version: "0.0.0".to_string(),
|
||||
source: SessionSource::Cli,
|
||||
model_provider: Some("test-provider".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
git: Some(GitInfo {
|
||||
commit_hash: None,
|
||||
branch: metadata.git_branch.clone(),
|
||||
repository_url: None,
|
||||
}),
|
||||
}),
|
||||
};
|
||||
let user_message = RolloutLine {
|
||||
timestamp,
|
||||
item: RolloutItem::EventMsg(EventMsg::UserMessage(UserMessageEvent {
|
||||
message: first_user_message.to_string(),
|
||||
images: None,
|
||||
local_images: Vec::new(),
|
||||
text_elements: Vec::new(),
|
||||
})),
|
||||
};
|
||||
fs::write(
|
||||
&rollout_path,
|
||||
format!(
|
||||
"{}\n{}\n",
|
||||
serde_json::to_string(&session_meta)?,
|
||||
serde_json::to_string(&user_message)?
|
||||
),
|
||||
)?;
|
||||
db.upsert_thread(&metadata).await?;
|
||||
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user