Skip to content

Commit b9e4fad

Browse files
committed
Propagate collab agent metadata and progress
1 parent c4a50dc commit b9e4fad

6 files changed

Lines changed: 362 additions & 34 deletions

File tree

codex-rs/app-server-protocol/src/protocol/event_mapping.rs

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::protocol::v2::ReasoningTextDeltaNotification;
1919
use crate::protocol::v2::TerminalInteractionNotification;
2020
use crate::protocol::v2::ThreadItem;
2121
use codex_protocol::dynamic_tools::DynamicToolCallOutputContentItem as CoreDynamicToolCallOutputContentItem;
22+
use codex_protocol::protocol::AgentStatus;
2223
use codex_protocol::protocol::EventMsg;
2324
use std::collections::HashMap;
2425

@@ -104,7 +105,11 @@ pub fn item_event_to_server_notification(
104105
let (receiver_thread_ids, agents_states) = match end_event.new_thread_id {
105106
Some(id) => {
106107
let receiver_id = id.to_string();
107-
let received_status = CollabAgentState::from(end_event.status.clone());
108+
let received_status = collab_agent_state(
109+
end_event.status.clone(),
110+
end_event.new_agent_nickname,
111+
end_event.new_agent_role,
112+
);
108113
(
109114
vec![receiver_id.clone()],
110115
[(receiver_id, received_status)].into_iter().collect(),
@@ -159,7 +164,11 @@ pub fn item_event_to_server_notification(
159164
_ => CollabAgentToolCallStatus::Completed,
160165
};
161166
let receiver_id = end_event.receiver_thread_id.to_string();
162-
let received_status = CollabAgentState::from(end_event.status);
167+
let received_status = collab_agent_state(
168+
end_event.status,
169+
end_event.receiver_agent_nickname,
170+
end_event.receiver_agent_role,
171+
);
163172
let item = ThreadItem::CollabAgentToolCall {
164173
id: end_event.call_id,
165174
tool: CollabAgentTool::SendInput,
@@ -215,10 +224,22 @@ pub fn item_event_to_server_notification(
215224
CollabAgentToolCallStatus::Completed
216225
};
217226
let receiver_thread_ids = end_event.statuses.keys().map(ToString::to_string).collect();
227+
let metadata_by_thread_id = end_event
228+
.agent_statuses
229+
.into_iter()
230+
.map(|entry| (entry.thread_id, (entry.agent_nickname, entry.agent_role)))
231+
.collect::<HashMap<_, _>>();
218232
let agents_states = end_event
219233
.statuses
220234
.iter()
221-
.map(|(id, status)| (id.to_string(), CollabAgentState::from(status.clone())))
235+
.map(|(id, status)| {
236+
let (agent_nickname, agent_role) =
237+
metadata_by_thread_id.get(id).cloned().unwrap_or_default();
238+
(
239+
id.to_string(),
240+
collab_agent_state(status.clone(), agent_nickname, agent_role),
241+
)
242+
})
222243
.collect();
223244
let item = ThreadItem::CollabAgentToolCall {
224245
id: end_event.call_id,
@@ -268,7 +289,11 @@ pub fn item_event_to_server_notification(
268289
let receiver_id = end_event.receiver_thread_id.to_string();
269290
let agents_states = [(
270291
receiver_id.clone(),
271-
CollabAgentState::from(end_event.status),
292+
collab_agent_state(
293+
end_event.status,
294+
end_event.receiver_agent_nickname,
295+
end_event.receiver_agent_role,
296+
),
272297
)]
273298
.into_iter()
274299
.collect();
@@ -320,7 +345,11 @@ pub fn item_event_to_server_notification(
320345
let receiver_id = end_event.receiver_thread_id.to_string();
321346
let agents_states = [(
322347
receiver_id.clone(),
323-
CollabAgentState::from(end_event.status),
348+
collab_agent_state(
349+
end_event.status,
350+
end_event.receiver_agent_nickname,
351+
end_event.receiver_agent_role,
352+
),
324353
)]
325354
.into_iter()
326355
.collect();
@@ -449,6 +478,14 @@ pub fn item_event_to_server_notification(
449478
}
450479
}
451480

481+
fn collab_agent_state(
482+
status: AgentStatus,
483+
agent_nickname: Option<String>,
484+
agent_role: Option<String>,
485+
) -> CollabAgentState {
486+
CollabAgentState::from(status).with_agent_metadata(agent_nickname, agent_role)
487+
}
488+
452489
#[cfg(test)]
453490
mod tests {
454491
use super::*;

codex-rs/app-server-protocol/src/protocol/thread_history.rs

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@ use std::collections::HashMap;
5858
use tracing::warn;
5959
use uuid::Uuid;
6060

61+
fn collab_agent_state(
62+
status: AgentStatus,
63+
agent_nickname: Option<String>,
64+
agent_role: Option<String>,
65+
) -> CollabAgentState {
66+
CollabAgentState::from(status).with_agent_metadata(agent_nickname, agent_role)
67+
}
68+
6169
#[cfg(test)]
6270
use crate::protocol::v2::CommandAction;
6371
#[cfg(test)]
@@ -634,7 +642,11 @@ impl ThreadHistoryBuilder {
634642
let (receiver_thread_ids, agents_states) = match &payload.new_thread_id {
635643
Some(id) => {
636644
let receiver_id = id.to_string();
637-
let received_status = CollabAgentState::from(payload.status.clone());
645+
let received_status = collab_agent_state(
646+
payload.status.clone(),
647+
payload.new_agent_nickname.clone(),
648+
payload.new_agent_role.clone(),
649+
);
638650
(
639651
vec![receiver_id.clone()],
640652
[(receiver_id, received_status)].into_iter().collect(),
@@ -682,7 +694,11 @@ impl ThreadHistoryBuilder {
682694
_ => CollabAgentToolCallStatus::Completed,
683695
};
684696
let receiver_id = payload.receiver_thread_id.to_string();
685-
let received_status = CollabAgentState::from(payload.status.clone());
697+
let received_status = collab_agent_state(
698+
payload.status.clone(),
699+
payload.receiver_agent_nickname.clone(),
700+
payload.receiver_agent_role.clone(),
701+
);
686702
self.upsert_item_in_current_turn(ThreadItem::CollabAgentToolCall {
687703
id: payload.call_id.clone(),
688704
tool: CollabAgentTool::SendInput,
@@ -734,10 +750,27 @@ impl ThreadHistoryBuilder {
734750
let mut receiver_thread_ids: Vec<String> =
735751
payload.statuses.keys().map(ToString::to_string).collect();
736752
receiver_thread_ids.sort();
753+
let metadata_by_thread_id = payload
754+
.agent_statuses
755+
.iter()
756+
.map(|entry| {
757+
(
758+
entry.thread_id,
759+
(entry.agent_nickname.clone(), entry.agent_role.clone()),
760+
)
761+
})
762+
.collect::<HashMap<_, _>>();
737763
let agents_states = payload
738764
.statuses
739765
.iter()
740-
.map(|(id, status)| (id.to_string(), CollabAgentState::from(status.clone())))
766+
.map(|(id, status)| {
767+
let (agent_nickname, agent_role) =
768+
metadata_by_thread_id.get(id).cloned().unwrap_or_default();
769+
(
770+
id.to_string(),
771+
collab_agent_state(status.clone(), agent_nickname, agent_role),
772+
)
773+
})
741774
.collect();
742775
self.upsert_item_in_current_turn(ThreadItem::CollabAgentToolCall {
743776
id: payload.call_id.clone(),
@@ -778,7 +811,11 @@ impl ThreadHistoryBuilder {
778811
let receiver_id = payload.receiver_thread_id.to_string();
779812
let agents_states = [(
780813
receiver_id.clone(),
781-
CollabAgentState::from(payload.status.clone()),
814+
collab_agent_state(
815+
payload.status.clone(),
816+
payload.receiver_agent_nickname.clone(),
817+
payload.receiver_agent_role.clone(),
818+
),
782819
)]
783820
.into_iter()
784821
.collect();
@@ -824,7 +861,11 @@ impl ThreadHistoryBuilder {
824861
let receiver_id = payload.receiver_thread_id.to_string();
825862
let agents_states = [(
826863
receiver_id.clone(),
827-
CollabAgentState::from(payload.status.clone()),
864+
collab_agent_state(
865+
payload.status.clone(),
866+
payload.receiver_agent_nickname.clone(),
867+
payload.receiver_agent_role.clone(),
868+
),
828869
)]
829870
.into_iter()
830871
.collect();
@@ -2785,6 +2826,8 @@ mod tests {
27852826
CollabAgentState {
27862827
status: crate::protocol::v2::CollabAgentStatus::Completed,
27872828
message: None,
2829+
agent_nickname: None,
2830+
agent_role: None,
27882831
},
27892832
)]
27902833
.into_iter()
@@ -2843,6 +2886,8 @@ mod tests {
28432886
CollabAgentState {
28442887
status: crate::protocol::v2::CollabAgentStatus::Running,
28452888
message: None,
2889+
agent_nickname: Some("Scout".into()),
2890+
agent_role: Some("explorer".into()),
28462891
},
28472892
)]
28482893
.into_iter()
@@ -2913,6 +2958,8 @@ mod tests {
29132958
CollabAgentState {
29142959
status: crate::protocol::v2::CollabAgentStatus::Interrupted,
29152960
message: None,
2961+
agent_nickname: None,
2962+
agent_role: None,
29162963
},
29172964
)]
29182965
.into_iter()

codex-rs/app-server-protocol/src/protocol/v2/item.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,10 @@ pub enum CollabAgentStatus {
10171017
pub struct CollabAgentState {
10181018
pub status: CollabAgentStatus,
10191019
pub message: Option<String>,
1020+
#[serde(default)]
1021+
pub agent_nickname: Option<String>,
1022+
#[serde(default)]
1023+
pub agent_role: Option<String>,
10201024
}
10211025

10221026
impl From<CoreAgentStatus> for CollabAgentState {
@@ -1025,35 +1029,61 @@ impl From<CoreAgentStatus> for CollabAgentState {
10251029
CoreAgentStatus::PendingInit => Self {
10261030
status: CollabAgentStatus::PendingInit,
10271031
message: None,
1032+
agent_nickname: None,
1033+
agent_role: None,
10281034
},
10291035
CoreAgentStatus::Running => Self {
10301036
status: CollabAgentStatus::Running,
10311037
message: None,
1038+
agent_nickname: None,
1039+
agent_role: None,
10321040
},
10331041
CoreAgentStatus::Interrupted => Self {
10341042
status: CollabAgentStatus::Interrupted,
10351043
message: None,
1044+
agent_nickname: None,
1045+
agent_role: None,
10361046
},
10371047
CoreAgentStatus::Completed(message) => Self {
10381048
status: CollabAgentStatus::Completed,
10391049
message,
1050+
agent_nickname: None,
1051+
agent_role: None,
10401052
},
10411053
CoreAgentStatus::Errored(message) => Self {
10421054
status: CollabAgentStatus::Errored,
10431055
message: Some(message),
1056+
agent_nickname: None,
1057+
agent_role: None,
10441058
},
10451059
CoreAgentStatus::Shutdown => Self {
10461060
status: CollabAgentStatus::Shutdown,
10471061
message: None,
1062+
agent_nickname: None,
1063+
agent_role: None,
10481064
},
10491065
CoreAgentStatus::NotFound => Self {
10501066
status: CollabAgentStatus::NotFound,
10511067
message: None,
1068+
agent_nickname: None,
1069+
agent_role: None,
10521070
},
10531071
}
10541072
}
10551073
}
10561074

1075+
impl CollabAgentState {
1076+
pub fn with_agent_metadata(
1077+
mut self,
1078+
agent_nickname: Option<String>,
1079+
agent_role: Option<String>,
1080+
) -> Self {
1081+
self.agent_nickname = agent_nickname;
1082+
self.agent_role = agent_role;
1083+
self
1084+
}
1085+
}
1086+
10571087
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
10581088
#[serde(rename_all = "camelCase")]
10591089
#[ts(export_to = "v2/")]

codex-rs/app-server-protocol/src/protocol/v2/tests.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,8 @@ fn collab_agent_state_maps_interrupted_status() {
195195
CollabAgentState {
196196
status: CollabAgentStatus::Interrupted,
197197
message: None,
198+
agent_nickname: None,
199+
agent_role: None,
198200
}
199201
);
200202
}

0 commit comments

Comments
 (0)