@@ -852,23 +852,10 @@ pub(crate) async fn apply_bespoke_event_handling(
852852 ) ;
853853 outgoing. send_server_notification ( notification) . await ;
854854 }
855- EventMsg :: SubAgentActivity ( activity) => {
856- if activity. kind == SubAgentActivityKind :: Interrupted
857- && thread_manager
858- . get_thread ( activity. agent_thread_id )
859- . await
860- . is_err ( )
861- {
862- thread_watch_manager
863- . remove_thread ( & activity. agent_thread_id . to_string ( ) )
864- . await ;
865- }
866- let notification = item_event_to_server_notification (
867- EventMsg :: SubAgentActivity ( activity) ,
868- & conversation_id. to_string ( ) ,
869- & event_turn_id,
870- ) ;
871- outgoing. send_server_notification ( notification) . await ;
855+ EventMsg :: SubAgentActivity ( _) => {
856+ // Deprecated sub-agent activity events are still fanned out for raw-event and
857+ // rollout compatibility consumers. App-server v2 receives the canonical
858+ // SubAgentActivity item lifecycle instead.
872859 }
873860 EventMsg :: CollabCloseEnd ( end_event) => {
874861 if thread_manager
@@ -1033,7 +1020,13 @@ pub(crate) async fn apply_bespoke_event_handling(
10331020 }
10341021 }
10351022 EventMsg :: ItemCompleted ( event) => {
1036- apply_canonical_item_completed_side_effects ( & thread_state, & event. item ) . await ;
1023+ apply_canonical_item_completed_side_effects (
1024+ & thread_manager,
1025+ & thread_watch_manager,
1026+ & thread_state,
1027+ & event. item ,
1028+ )
1029+ . await ;
10371030 let notification = item_event_to_server_notification (
10381031 EventMsg :: ItemCompleted ( event) ,
10391032 & conversation_id. to_string ( ) ,
@@ -1334,16 +1327,43 @@ async fn emit_turn_completed_with_status(
13341327}
13351328
13361329async fn apply_canonical_item_completed_side_effects (
1330+ thread_manager : & Arc < ThreadManager > ,
1331+ thread_watch_manager : & ThreadWatchManager ,
13371332 thread_state : & Arc < Mutex < ThreadState > > ,
13381333 item : & CoreTurnItem ,
13391334) {
1340- if let CoreTurnItem :: CommandExecution ( item) = item {
1341- thread_state
1342- . lock ( )
1343- . await
1344- . turn_summary
1345- . command_execution_started
1346- . remove ( & item. id ) ;
1335+ match item {
1336+ CoreTurnItem :: CommandExecution ( item) => {
1337+ thread_state
1338+ . lock ( )
1339+ . await
1340+ . turn_summary
1341+ . command_execution_started
1342+ . remove ( & item. id ) ;
1343+ }
1344+ CoreTurnItem :: SubAgentActivity ( activity)
1345+ if activity. kind == SubAgentActivityKind :: Interrupted =>
1346+ {
1347+ remove_missing_thread_watch (
1348+ thread_manager,
1349+ thread_watch_manager,
1350+ activity. agent_thread_id ,
1351+ )
1352+ . await ;
1353+ }
1354+ _ => { }
1355+ }
1356+ }
1357+
1358+ async fn remove_missing_thread_watch (
1359+ thread_manager : & Arc < ThreadManager > ,
1360+ thread_watch_manager : & ThreadWatchManager ,
1361+ thread_id : ThreadId ,
1362+ ) {
1363+ if thread_manager. get_thread ( thread_id) . await . is_err ( ) {
1364+ thread_watch_manager
1365+ . remove_thread ( & thread_id. to_string ( ) )
1366+ . await ;
13471367 }
13481368}
13491369
@@ -2175,6 +2195,7 @@ mod tests {
21752195 use codex_protocol:: items:: DynamicToolCallItem ;
21762196 use codex_protocol:: items:: DynamicToolCallStatus as CoreDynamicToolCallStatus ;
21772197 use codex_protocol:: items:: HookPromptFragment ;
2198+ use codex_protocol:: items:: SubAgentActivityItem ;
21782199 use codex_protocol:: items:: TurnItem as CoreTurnItem ;
21792200 use codex_protocol:: items:: build_hook_prompt_message;
21802201 use codex_protocol:: models:: FileSystemPermissions as CoreFileSystemPermissions ;
@@ -2192,12 +2213,12 @@ mod tests {
21922213 use codex_protocol:: protocol:: EventMsg ;
21932214 use codex_protocol:: protocol:: GuardianAssessmentEvent ;
21942215 use codex_protocol:: protocol:: GuardianAssessmentStatus ;
2216+ use codex_protocol:: protocol:: ItemCompletedEvent ;
21952217 use codex_protocol:: protocol:: ItemStartedEvent ;
21962218 use codex_protocol:: protocol:: RateLimitSnapshot ;
21972219 use codex_protocol:: protocol:: RateLimitWindow ;
21982220 use codex_protocol:: protocol:: RolloutItem ;
21992221 use codex_protocol:: protocol:: SessionSource ;
2200- use codex_protocol:: protocol:: SubAgentActivityEvent ;
22012222 use codex_protocol:: protocol:: TokenUsage ;
22022223 use codex_protocol:: protocol:: TokenUsageInfo ;
22032224 use codex_protocol:: protocol:: UserMessageEvent ;
@@ -3420,13 +3441,17 @@ mod tests {
34203441 apply_bespoke_event_handling (
34213442 Event {
34223443 id : "turn-1" . to_string ( ) ,
3423- msg : EventMsg :: SubAgentActivity ( SubAgentActivityEvent {
3424- event_id : "activity-1" . to_string ( ) ,
3425- occurred_at_ms : 42 ,
3426- agent_thread_id : child_thread_id,
3427- agent_path : AgentPath :: try_from ( "/root/worker" )
3428- . expect ( "agent path should parse" ) ,
3429- kind : SubAgentActivityKind :: Interrupted ,
3444+ msg : EventMsg :: ItemCompleted ( ItemCompletedEvent {
3445+ thread_id : conversation_id,
3446+ turn_id : "turn-1" . to_string ( ) ,
3447+ item : CoreTurnItem :: SubAgentActivity ( SubAgentActivityItem {
3448+ id : "activity-1" . to_string ( ) ,
3449+ kind : SubAgentActivityKind :: Interrupted ,
3450+ agent_thread_id : child_thread_id,
3451+ agent_path : AgentPath :: try_from ( "/root/worker" )
3452+ . expect ( "agent path should parse" ) ,
3453+ } ) ,
3454+ completed_at_ms : 42 ,
34303455 } ) ,
34313456 } ,
34323457 conversation_id,
0 commit comments