mirror of
https://github.com/openai/codex.git
synced 2026-04-30 01:16:54 +00:00
feat: add nick name to sub-agents (#12320)
Adding random nick name to sub-agents. Used for UX At the same time, also storing and wiring the role of the sub-agent
This commit is contained in:
@@ -6658,6 +6658,8 @@ async fn read_summary_from_state_db_context_by_thread_id(
|
||||
metadata.cwd,
|
||||
metadata.cli_version,
|
||||
metadata.source,
|
||||
metadata.agent_nickname,
|
||||
metadata.agent_role,
|
||||
metadata.git_sha,
|
||||
metadata.git_branch,
|
||||
metadata.git_origin_url,
|
||||
@@ -6678,9 +6680,12 @@ async fn summary_from_thread_list_item(
|
||||
.unwrap_or_else(|| fallback_provider.to_string());
|
||||
let cwd = it.cwd?;
|
||||
let cli_version = it.cli_version.unwrap_or_default();
|
||||
let source = it
|
||||
.source
|
||||
.unwrap_or(codex_protocol::protocol::SessionSource::Unknown);
|
||||
let source = with_thread_spawn_agent_metadata(
|
||||
it.source
|
||||
.unwrap_or(codex_protocol::protocol::SessionSource::Unknown),
|
||||
it.agent_nickname.clone(),
|
||||
it.agent_role.clone(),
|
||||
);
|
||||
return Some(ConversationSummary {
|
||||
conversation_id: thread_id,
|
||||
path: it.path,
|
||||
@@ -6735,13 +6740,17 @@ fn summary_from_state_db_metadata(
|
||||
cwd: PathBuf,
|
||||
cli_version: String,
|
||||
source: String,
|
||||
agent_nickname: Option<String>,
|
||||
agent_role: Option<String>,
|
||||
git_sha: Option<String>,
|
||||
git_branch: Option<String>,
|
||||
git_origin_url: Option<String>,
|
||||
) -> ConversationSummary {
|
||||
let preview = first_user_message.unwrap_or_default();
|
||||
let source = serde_json::from_value(serde_json::Value::String(source))
|
||||
let source = serde_json::from_str(&source)
|
||||
.or_else(|_| serde_json::from_value(serde_json::Value::String(source.clone())))
|
||||
.unwrap_or(codex_protocol::protocol::SessionSource::Unknown);
|
||||
let source = with_thread_spawn_agent_metadata(source, agent_nickname, agent_role);
|
||||
let git_info = if git_sha.is_none() && git_branch.is_none() && git_origin_url.is_none() {
|
||||
None
|
||||
} else {
|
||||
@@ -6901,6 +6910,35 @@ fn map_git_info(git_info: &CoreGitInfo) -> ConversationGitInfo {
|
||||
}
|
||||
}
|
||||
|
||||
fn with_thread_spawn_agent_metadata(
|
||||
source: codex_protocol::protocol::SessionSource,
|
||||
agent_nickname: Option<String>,
|
||||
agent_role: Option<String>,
|
||||
) -> codex_protocol::protocol::SessionSource {
|
||||
if agent_nickname.is_none() && agent_role.is_none() {
|
||||
return source;
|
||||
}
|
||||
|
||||
match source {
|
||||
codex_protocol::protocol::SessionSource::SubAgent(
|
||||
codex_protocol::protocol::SubAgentSource::ThreadSpawn {
|
||||
parent_thread_id,
|
||||
depth,
|
||||
agent_nickname: existing_agent_nickname,
|
||||
agent_role: existing_agent_role,
|
||||
},
|
||||
) => codex_protocol::protocol::SessionSource::SubAgent(
|
||||
codex_protocol::protocol::SubAgentSource::ThreadSpawn {
|
||||
parent_thread_id,
|
||||
depth,
|
||||
agent_nickname: agent_nickname.or(existing_agent_nickname),
|
||||
agent_role: agent_role.or(existing_agent_role),
|
||||
},
|
||||
),
|
||||
_ => source,
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_datetime(timestamp: Option<&str>) -> Option<DateTime<Utc>> {
|
||||
timestamp.and_then(|ts| {
|
||||
chrono::DateTime::parse_from_rfc3339(ts)
|
||||
@@ -6937,6 +6975,8 @@ fn build_thread_from_snapshot(
|
||||
path,
|
||||
cwd: config_snapshot.cwd.clone(),
|
||||
cli_version: env!("CARGO_PKG_VERSION").to_string(),
|
||||
agent_nickname: config_snapshot.session_source.get_nickname(),
|
||||
agent_role: config_snapshot.session_source.get_agent_role(),
|
||||
source: config_snapshot.session_source.clone().into(),
|
||||
git_info: None,
|
||||
turns: Vec::new(),
|
||||
@@ -6975,6 +7015,8 @@ pub(crate) fn summary_to_thread(summary: ConversationSummary) -> Thread {
|
||||
path: Some(path),
|
||||
cwd,
|
||||
cli_version,
|
||||
agent_nickname: source.get_nickname(),
|
||||
agent_role: source.get_agent_role(),
|
||||
source: source.into(),
|
||||
git_info,
|
||||
turns: Vec::new(),
|
||||
@@ -6986,6 +7028,7 @@ mod tests {
|
||||
use super::*;
|
||||
use anyhow::Result;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use codex_protocol::protocol::SubAgentSource;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::json;
|
||||
use std::path::PathBuf;
|
||||
@@ -7131,6 +7174,41 @@ mod tests {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn summary_from_state_db_metadata_preserves_agent_nickname() -> Result<()> {
|
||||
let conversation_id = ThreadId::from_string("bfd12a78-5900-467b-9bc5-d3d35df08191")?;
|
||||
let source =
|
||||
serde_json::to_string(&SessionSource::SubAgent(SubAgentSource::ThreadSpawn {
|
||||
parent_thread_id: ThreadId::from_string("ad7f0408-99b8-4f6e-a46f-bd0eec433370")?,
|
||||
depth: 1,
|
||||
agent_nickname: None,
|
||||
agent_role: None,
|
||||
}))?;
|
||||
|
||||
let summary = summary_from_state_db_metadata(
|
||||
conversation_id,
|
||||
PathBuf::from("/tmp/rollout.jsonl"),
|
||||
Some("hi".to_string()),
|
||||
"2025-09-05T16:53:11Z".to_string(),
|
||||
"2025-09-05T16:53:12Z".to_string(),
|
||||
"test-provider".to_string(),
|
||||
PathBuf::from("/"),
|
||||
"0.0.0".to_string(),
|
||||
source,
|
||||
Some("atlas".to_string()),
|
||||
Some("explorer".to_string()),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
||||
let thread = summary_to_thread(summary);
|
||||
|
||||
assert_eq!(thread.agent_nickname, Some("atlas".to_string()));
|
||||
assert_eq!(thread.agent_role, Some("explorer".to_string()));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn removing_one_listener_does_not_cancel_other_subscriptions_for_same_thread()
|
||||
-> Result<()> {
|
||||
|
||||
Reference in New Issue
Block a user