mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
chore: morpheus to path (#18353)
Make the morpheus agent (which is the phase 2 memories agent) follow the agent-v2 path system by naming it `/morpheus`. To maintain the path primitive this means moving it to a dedicated `AgentControl` Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
e404c4e910
commit
b528ff02b6
@@ -148,6 +148,15 @@ impl AgentControl {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a control-plane handle over the same thread manager with an independent live-agent
|
||||
/// registry.
|
||||
pub(crate) fn detached_registry(&self) -> Self {
|
||||
Self {
|
||||
manager: self.manager.clone(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Spawn a new agent thread and submit the initial prompt.
|
||||
pub(crate) async fn spawn_agent(
|
||||
&self,
|
||||
|
||||
@@ -139,9 +139,8 @@ pub(super) async fn run(session: &Arc<Session>, config: Arc<Config>) {
|
||||
// 5. Spawn the agent
|
||||
let prompt = agent::get_prompt(config, &selection, &removed_extension_resources);
|
||||
let source = SessionSource::SubAgent(SubAgentSource::MemoryConsolidation);
|
||||
let thread_id = match session
|
||||
.services
|
||||
.agent_control
|
||||
let agent_control = session.services.agent_control.detached_registry();
|
||||
let thread_id = match agent_control
|
||||
.spawn_agent(agent_config, prompt.into(), Some(source))
|
||||
.await
|
||||
{
|
||||
@@ -182,6 +181,7 @@ pub(super) async fn run(session: &Arc<Session>, config: Arc<Config>) {
|
||||
raw_memories.clone(),
|
||||
pending_extension_resource_removals,
|
||||
thread_id,
|
||||
agent_control,
|
||||
phase_two_e2e_timer,
|
||||
);
|
||||
|
||||
@@ -369,6 +369,7 @@ mod agent {
|
||||
selected_outputs: Vec<codex_state::Stage1Output>,
|
||||
pending_extension_resource_removals: Vec<PendingExtensionResourceRemoval>,
|
||||
thread_id: ThreadId,
|
||||
agent_control: crate::agent::AgentControl,
|
||||
phase_two_e2e_timer: Option<codex_otel::Timer>,
|
||||
) {
|
||||
let Some(db) = session.services.state_db.clone() else {
|
||||
@@ -378,7 +379,6 @@ mod agent {
|
||||
|
||||
tokio::spawn(async move {
|
||||
let _phase_two_e2e_timer = phase_two_e2e_timer;
|
||||
let agent_control = session.services.agent_control.clone();
|
||||
|
||||
// TODO(jif) we might have a very small race here.
|
||||
let rx = match agent_control.subscribe_status(thread_id).await {
|
||||
|
||||
@@ -429,6 +429,7 @@ mod phase2 {
|
||||
use codex_config::Constrained;
|
||||
use codex_features::Feature;
|
||||
use codex_login::CodexAuth;
|
||||
use codex_protocol::AgentPath;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::permissions::FileSystemSandboxPolicy;
|
||||
use codex_protocol::permissions::NetworkSandboxPolicy;
|
||||
@@ -703,6 +704,19 @@ mod phase2 {
|
||||
}
|
||||
other => panic!("unexpected sandbox policy: {other:?}"),
|
||||
}
|
||||
pretty_assertions::assert_eq!(
|
||||
config_snapshot.session_source.get_agent_path(),
|
||||
Some(AgentPath::morpheus())
|
||||
);
|
||||
assert!(
|
||||
harness
|
||||
.session
|
||||
.services
|
||||
.agent_control
|
||||
.get_agent_metadata(thread_id)
|
||||
.is_none(),
|
||||
"memory consolidation should not be registered in the root collab agent registry"
|
||||
);
|
||||
let turn_context = subagent.codex.session.new_default_turn().await;
|
||||
pretty_assertions::assert_eq!(
|
||||
turn_context.file_system_sandbox_policy,
|
||||
|
||||
@@ -16,12 +16,17 @@ pub struct AgentPath(String);
|
||||
|
||||
impl AgentPath {
|
||||
pub const ROOT: &str = "/root";
|
||||
pub const MORPHEUS: &str = "/morpheus";
|
||||
const ROOT_SEGMENT: &str = "root";
|
||||
|
||||
pub fn root() -> Self {
|
||||
Self(Self::ROOT.to_string())
|
||||
}
|
||||
|
||||
pub fn morpheus() -> Self {
|
||||
Self(Self::MORPHEUS.to_string())
|
||||
}
|
||||
|
||||
pub fn from_string(path: String) -> Result<Self, String> {
|
||||
validate_absolute_path(path.as_str())?;
|
||||
Ok(Self(path))
|
||||
@@ -142,15 +147,19 @@ fn validate_agent_name(agent_name: &str) -> Result<(), String> {
|
||||
}
|
||||
|
||||
fn validate_absolute_path(path: &str) -> Result<(), String> {
|
||||
if path == AgentPath::MORPHEUS {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let Some(stripped) = path.strip_prefix('/') else {
|
||||
return Err("absolute agent paths must start with `/root`".to_string());
|
||||
return Err("absolute agent paths must start with `/root` or be `/morpheus`".to_string());
|
||||
};
|
||||
let mut segments = stripped.split('/');
|
||||
let Some(root) = segments.next() else {
|
||||
return Err("absolute agent path must not be empty".to_string());
|
||||
};
|
||||
if root != AgentPath::ROOT_SEGMENT {
|
||||
return Err("absolute agent paths must start with `/root`".to_string());
|
||||
return Err("absolute agent paths must start with `/root` or be `/morpheus`".to_string());
|
||||
}
|
||||
if stripped.ends_with('/') {
|
||||
return Err("absolute agent path must not end with `/`".to_string());
|
||||
@@ -184,6 +193,14 @@ mod tests {
|
||||
assert!(root.is_root());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn morpheus_has_expected_name() {
|
||||
let morpheus = AgentPath::morpheus();
|
||||
assert_eq!(morpheus.as_str(), AgentPath::MORPHEUS);
|
||||
assert_eq!(morpheus.name(), "morpheus");
|
||||
assert!(!morpheus.is_root());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn join_builds_child_paths() {
|
||||
let root = AgentPath::root();
|
||||
@@ -213,7 +230,7 @@ mod tests {
|
||||
);
|
||||
assert_eq!(
|
||||
AgentPath::try_from("/not-root"),
|
||||
Err("absolute agent paths must start with `/root`".to_string())
|
||||
Err("absolute agent paths must start with `/root` or be `/morpheus`".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
AgentPath::root().resolve("../sibling"),
|
||||
|
||||
@@ -2723,6 +2723,9 @@ impl SessionSource {
|
||||
SessionSource::SubAgent(SubAgentSource::ThreadSpawn { agent_path, .. }) => {
|
||||
agent_path.clone()
|
||||
}
|
||||
SessionSource::SubAgent(SubAgentSource::MemoryConsolidation) => {
|
||||
Some(AgentPath::morpheus())
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user