@@ -20,6 +20,7 @@ use std::sync::Arc;
2020
2121use crate :: anthropic:: error:: json_error;
2222use crate :: anthropic:: schema:: { CountTokensResponse , MessagesRequest } ;
23+ use crate :: anthropic:: sse:: parse_sse_events;
2324use crate :: config;
2425use crate :: logging:: create_logger;
2526use crate :: monitor:: usage_from_anthropic_sse;
@@ -563,7 +564,7 @@ async fn live_stream_response_once(
563564 generation_started = true ;
564565 }
565566 append_upstream_sse_payload ( & mut upstream_sse_body, & payload) ;
566- let ( chunk, terminal) = match translate_live_stream_payload ( & mut translator, & payload, & ctx )
567+ let ( chunk, terminal) = match translate_live_stream_payload ( & mut translator, & payload, None )
567568 {
568569 Ok ( result) => result,
569570 Err ( message) => {
@@ -619,6 +620,7 @@ async fn live_stream_response_once(
619620 } ;
620621 }
621622 if translator. has_semantic_output ( ) && !pending_chunk. is_empty ( ) {
623+ record_live_stream_downstream_capture ( & ctx, & pending_chunk) ;
622624 record_live_stream_progress ( & ctx, & pending_chunk) ;
623625 if terminal {
624626 update_continuation_from_upstream (
@@ -652,6 +654,7 @@ async fn live_stream_response_once(
652654 if pending_chunk. is_empty ( ) {
653655 return LiveStreamStart :: Response ( empty_live_stream_response ( ) ) ;
654656 }
657+ record_live_stream_downstream_capture ( & ctx, & pending_chunk) ;
655658 record_live_stream_progress ( & ctx, & pending_chunk) ;
656659 return LiveStreamStart :: Response ( single_live_stream_response ( pending_chunk) ) ;
657660 }
@@ -688,13 +691,31 @@ fn codex_generation_event(payload: &serde_json::Value) -> bool {
688691fn translate_live_stream_payload (
689692 translator : & mut LiveStreamTranslator ,
690693 payload : & serde_json:: Value ,
691- ctx : & RequestContext ,
694+ traffic : Option < & crate :: traffic :: TrafficCapture > ,
692695) -> Result < ( Vec < u8 > , bool ) , String > {
693- let chunk = translator. accept ( payload, ctx . traffic . as_deref ( ) ) ?;
696+ let chunk = translator. accept ( payload, traffic) ?;
694697 let terminal = is_codex_terminal_event ( payload) || translator. is_finished ( ) ;
695698 Ok ( ( chunk, terminal) )
696699}
697700
701+ fn record_live_stream_downstream_capture ( ctx : & RequestContext , chunk : & [ u8 ] ) {
702+ let Some ( traffic) = ctx. traffic . as_ref ( ) else {
703+ return ;
704+ } ;
705+ for event in parse_sse_events ( chunk) {
706+ let Ok ( data) = serde_json:: from_str :: < serde_json:: Value > ( & event. data ) else {
707+ continue ;
708+ } ;
709+ traffic. write_json_event (
710+ "050-downstream-event" ,
711+ & serde_json:: json!( {
712+ "event" : event. event. as_deref( ) . unwrap_or( "message" ) ,
713+ "data" : data,
714+ } ) ,
715+ ) ;
716+ }
717+ }
718+
698719fn record_live_stream_progress ( ctx : & RequestContext , chunk : & [ u8 ] ) {
699720 if let Some ( monitor) = ctx. monitor . as_ref ( ) {
700721 let ( input_tokens, output_tokens) = usage_from_anthropic_sse ( chunk) ;
@@ -744,28 +765,31 @@ fn remaining_live_stream_response(
744765 match item {
745766 Ok ( payload) => {
746767 append_upstream_sse_payload ( & mut upstream_sse_body, & payload) ;
747- let ( chunk, terminal) =
748- match translate_live_stream_payload ( & mut translator, & payload, & ctx) {
749- Ok ( result) => result,
750- Err ( message) => {
751- abort_request_state (
752- ctx. session_id . as_deref ( ) ,
753- turn_id,
754- compact_boundary,
755- & request_body,
756- ) ;
757- let chunk = translator. error_chunk (
758- & message,
759- "api_error" ,
760- ctx. traffic . as_deref ( ) ,
761- ) ;
762- if !chunk. is_empty ( ) {
763- record_live_stream_progress ( & ctx, & chunk) ;
764- let _ = tx. send ( Ok ( Bytes :: from ( chunk) ) ) . await ;
765- }
766- return ;
768+ let ( chunk, terminal) = match translate_live_stream_payload (
769+ & mut translator,
770+ & payload,
771+ ctx. traffic . as_deref ( ) ,
772+ ) {
773+ Ok ( result) => result,
774+ Err ( message) => {
775+ abort_request_state (
776+ ctx. session_id . as_deref ( ) ,
777+ turn_id,
778+ compact_boundary,
779+ & request_body,
780+ ) ;
781+ let chunk = translator. error_chunk (
782+ & message,
783+ "api_error" ,
784+ ctx. traffic . as_deref ( ) ,
785+ ) ;
786+ if !chunk. is_empty ( ) {
787+ record_live_stream_progress ( & ctx, & chunk) ;
788+ let _ = tx. send ( Ok ( Bytes :: from ( chunk) ) ) . await ;
767789 }
768- } ;
790+ return ;
791+ }
792+ } ;
769793 if !chunk. is_empty ( ) {
770794 record_live_stream_progress ( & ctx, & chunk) ;
771795 if tx. send ( Ok ( Bytes :: from ( chunk) ) ) . await . is_err ( ) {
0 commit comments