mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
feat: ordinal nick name (#13412)
This commit is contained in:
committed by
GitHub
Unverified
parent
932ff28183
commit
a4ad101125
@@ -30,6 +30,26 @@ struct ActiveAgents {
|
||||
used_agent_nicknames: HashSet<String>,
|
||||
nickname_reset_count: usize,
|
||||
}
|
||||
|
||||
fn format_agent_nickname(name: &str, nickname_reset_count: usize) -> String {
|
||||
match nickname_reset_count {
|
||||
0 => name.to_string(),
|
||||
reset_count => {
|
||||
let value = reset_count + 1;
|
||||
let suffix = match value % 100 {
|
||||
11..=13 => "th",
|
||||
_ => match value % 10 {
|
||||
1 => "st", // codespell:ignore
|
||||
2 => "nd", // codespell:ignore
|
||||
3 => "rd", // codespell:ignore
|
||||
_ => "th", // codespell:ignore
|
||||
},
|
||||
};
|
||||
format!("{name} the {value}{suffix}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn session_depth(session_source: &SessionSource) -> i32 {
|
||||
match session_source {
|
||||
SessionSource::SubAgent(SubAgentSource::ThreadSpawn { depth, .. }) => *depth,
|
||||
@@ -107,20 +127,23 @@ impl Guards {
|
||||
if names.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let available_names: Vec<&str> = names
|
||||
let available_names: Vec<String> = names
|
||||
.iter()
|
||||
.copied()
|
||||
.filter(|name| !active_agents.used_agent_nicknames.contains(*name))
|
||||
.map(|name| format_agent_nickname(name, active_agents.nickname_reset_count))
|
||||
.filter(|name| !active_agents.used_agent_nicknames.contains(name))
|
||||
.collect();
|
||||
if let Some(name) = available_names.choose(&mut rand::rng()) {
|
||||
(*name).to_string()
|
||||
name.clone()
|
||||
} else {
|
||||
active_agents.used_agent_nicknames.clear();
|
||||
active_agents.nickname_reset_count += 1;
|
||||
if let Some(metrics) = codex_otel::metrics::global() {
|
||||
let _ = metrics.counter("codex.multi_agent.nickname_pool_reset", 1, &[]);
|
||||
}
|
||||
names.choose(&mut rand::rng())?.to_string()
|
||||
format_agent_nickname(
|
||||
names.choose(&mut rand::rng())?,
|
||||
active_agents.nickname_reset_count,
|
||||
)
|
||||
}
|
||||
};
|
||||
active_agents
|
||||
@@ -202,6 +225,16 @@ impl Drop for SpawnReservation {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[test]
|
||||
fn format_agent_nickname_adds_ordinals_after_reset() {
|
||||
assert_eq!(format_agent_nickname("Plato", 0), "Plato");
|
||||
assert_eq!(format_agent_nickname("Plato", 1), "Plato the 2nd");
|
||||
assert_eq!(format_agent_nickname("Plato", 2), "Plato the 3rd");
|
||||
assert_eq!(format_agent_nickname("Plato", 10), "Plato the 11th");
|
||||
assert_eq!(format_agent_nickname("Plato", 20), "Plato the 21st");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn session_depth_defaults_to_zero_for_root_sources() {
|
||||
@@ -352,7 +385,7 @@ mod tests {
|
||||
let second_name = second
|
||||
.reserve_agent_nickname(&["alpha"])
|
||||
.expect("name should be reused after pool reset");
|
||||
assert_eq!(second_name, "alpha");
|
||||
assert_eq!(second_name, "alpha the 2nd");
|
||||
let active_agents = guards
|
||||
.active_agents
|
||||
.lock()
|
||||
@@ -389,11 +422,49 @@ mod tests {
|
||||
let third_name = third
|
||||
.reserve_agent_nickname(&["alpha", "beta"])
|
||||
.expect("pool reset should permit a duplicate");
|
||||
assert!(third_name == "alpha" || third_name == "beta");
|
||||
let expected_names =
|
||||
HashSet::from(["alpha the 2nd".to_string(), "beta the 2nd".to_string()]);
|
||||
assert!(expected_names.contains(&third_name));
|
||||
let active_agents = guards
|
||||
.active_agents
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
assert_eq!(active_agents.nickname_reset_count, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn repeated_resets_advance_the_ordinal_suffix() {
|
||||
let guards = Arc::new(Guards::default());
|
||||
|
||||
let mut first = guards.reserve_spawn_slot(None).expect("reserve first slot");
|
||||
let first_name = first
|
||||
.reserve_agent_nickname(&["Plato"])
|
||||
.expect("reserve first agent name");
|
||||
let first_id = ThreadId::new();
|
||||
first.commit(first_id);
|
||||
assert_eq!(first_name, "Plato");
|
||||
guards.release_spawned_thread(first_id);
|
||||
|
||||
let mut second = guards
|
||||
.reserve_spawn_slot(None)
|
||||
.expect("reserve second slot");
|
||||
let second_name = second
|
||||
.reserve_agent_nickname(&["Plato"])
|
||||
.expect("reserve second agent name");
|
||||
let second_id = ThreadId::new();
|
||||
second.commit(second_id);
|
||||
assert_eq!(second_name, "Plato the 2nd");
|
||||
guards.release_spawned_thread(second_id);
|
||||
|
||||
let mut third = guards.reserve_spawn_slot(None).expect("reserve third slot");
|
||||
let third_name = third
|
||||
.reserve_agent_nickname(&["Plato"])
|
||||
.expect("reserve third agent name");
|
||||
assert_eq!(third_name, "Plato the 3rd");
|
||||
let active_agents = guards
|
||||
.active_agents
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
assert_eq!(active_agents.nickname_reset_count, 2);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user