1+ use crate :: client:: rpc_reply;
12use crate :: jsonrpc:: extract_request_id;
2- use crate :: nats:: { FlushClient , PublishClient , headers_with_trace_context } ;
3+ use crate :: nats:: { FlushClient , PublishClient } ;
34use agent_client_protocol:: {
4- Client , Error , ErrorCode , ReadTextFileRequest , ReadTextFileResponse , Request , RequestId ,
5- Response ,
5+ Client , ErrorCode , ReadTextFileRequest , ReadTextFileResponse , Request , Response ,
66} ;
77use bytes:: Bytes ;
88use serde:: de:: Error as SerdeDeError ;
99use tracing:: { instrument, warn} ;
1010use trogon_std:: JsonSerialize ;
1111
12- const CONTENT_TYPE_JSON : & str = "application/json" ;
13- const CONTENT_TYPE_PLAIN : & str = "text/plain" ;
14-
15- fn error_response_fallback_bytes < S : JsonSerialize > ( serializer : & S ) -> ( Bytes , & ' static str ) {
16- match serializer. to_vec ( & Response :: < ( ) > :: Error {
17- id : RequestId :: Null ,
18- error : Error :: new ( -32603 , "Internal error" ) ,
19- } ) {
20- Ok ( v) => ( Bytes :: from ( v) , CONTENT_TYPE_JSON ) ,
21- Err ( e) => {
22- warn ! (
23- error = %e,
24- "Fallback JSON serialization failed, response may not be valid JSON-RPC"
25- ) ;
26- ( Bytes :: from ( "Internal error" ) , CONTENT_TYPE_PLAIN )
27- }
28- }
29- }
30-
31- async fn publish_reply < N : PublishClient + FlushClient > (
32- nats : & N ,
33- reply_to : & str ,
34- bytes : Bytes ,
35- content_type : & str ,
36- context : & str ,
37- ) {
38- let mut headers = headers_with_trace_context ( ) ;
39- headers. insert ( "Content-Type" , content_type) ;
40- if let Err ( e) = nats
41- . publish_with_headers ( reply_to. to_string ( ) , headers, bytes)
42- . await
43- {
44- warn ! ( error = %e, "Failed to publish {}" , context) ;
45- }
46- if let Err ( e) = nats. flush ( ) . await {
47- warn ! ( error = %e, "Failed to flush {}" , context) ;
48- }
49- }
50-
51- fn error_response_bytes < S : JsonSerialize > (
52- serializer : & S ,
53- request_id : RequestId ,
54- code : ErrorCode ,
55- message : & str ,
56- ) -> ( Bytes , & ' static str ) {
57- let response = Response :: < ( ) > :: Error {
58- id : request_id,
59- error : Error :: new ( i32:: from ( code) , message) ,
60- } ;
61- match serializer. to_vec ( & response) {
62- Ok ( v) => ( Bytes :: from ( v) , CONTENT_TYPE_JSON ) ,
63- Err ( e) => {
64- warn ! ( error = %e, "JSON serialization failed, using fallback error" ) ;
65- error_response_fallback_bytes ( serializer)
66- }
67- }
68- }
69-
7012#[ derive( Debug ) ]
7113pub enum FsReadTextFileError {
7214 InvalidRequest ( serde_json:: Error ) ,
@@ -134,17 +76,17 @@ pub async fn handle<N: PublishClient + FlushClient, C: Client, S: JsonSerialize>
13476 id : request_id. clone ( ) ,
13577 result : response,
13678 } )
137- . map ( |v| ( Bytes :: from ( v) , CONTENT_TYPE_JSON ) )
79+ . map ( |v| ( Bytes :: from ( v) , rpc_reply :: CONTENT_TYPE_JSON ) )
13880 . unwrap_or_else ( |e| {
13981 warn ! ( error = %e, "JSON serialization of response failed, sending error reply" ) ;
140- error_response_bytes (
82+ rpc_reply :: error_response_bytes (
14183 serializer,
14284 request_id,
14385 ErrorCode :: InternalError ,
14486 & format ! ( "Failed to serialize response: {}" , e) ,
14587 )
14688 } ) ;
147- publish_reply (
89+ rpc_reply :: publish_reply (
14890 nats,
14991 reply_to,
15092 response_bytes,
@@ -161,8 +103,8 @@ pub async fn handle<N: PublishClient + FlushClient, C: Client, S: JsonSerialize>
161103 "Failed to handle fs_read_text_file"
162104 ) ;
163105 let ( bytes, content_type) =
164- error_response_bytes ( serializer, request_id, code, & message) ;
165- publish_reply (
106+ rpc_reply :: error_response_bytes ( serializer, request_id, code, & message) ;
107+ rpc_reply :: publish_reply (
166108 nats,
167109 reply_to,
168110 bytes,
@@ -634,21 +576,6 @@ mod tests {
634576 assert ! ( fs_err. source( ) . is_some( ) ) ;
635577 }
636578
637- #[ test]
638- fn error_response_bytes_first_fallback_uses_null_id ( ) {
639- let mock = FailNextSerialize :: new ( 1 ) ;
640- let ( bytes, content_type) = error_response_bytes (
641- & mock,
642- RequestId :: Number ( 42 ) ,
643- ErrorCode :: InvalidParams ,
644- "test message" ,
645- ) ;
646- assert_eq ! ( content_type, "application/json" ) ;
647- let parsed: serde_json:: Value = serde_json:: from_slice ( & bytes) . unwrap ( ) ;
648- assert_eq ! ( parsed[ "id" ] , serde_json:: Value :: Null ) ;
649- assert_eq ! ( parsed[ "error" ] [ "code" ] , -32603 ) ;
650- }
651-
652579 #[ tokio:: test]
653580 async fn mock_client_request_permission_returns_err ( ) {
654581 let client = MockClient :: new ( "x" ) ;
@@ -674,22 +601,4 @@ mod tests {
674601 let result = client. request_permission ( req) . await ;
675602 assert ! ( result. is_err( ) ) ;
676603 }
677-
678- #[ test]
679- fn error_response_bytes_last_resort_returns_plain_text ( ) {
680- let mock = FailNextSerialize :: new ( 2 ) ;
681- let ( bytes, content_type) =
682- error_response_bytes ( & mock, RequestId :: Number ( 1 ) , ErrorCode :: InternalError , "msg" ) ;
683- assert_eq ! ( content_type, "text/plain" ) ;
684- assert_eq ! ( bytes. as_ref( ) , b"Internal error" ) ;
685- }
686-
687- #[ test]
688- fn error_response_fallback_bytes_std_serializer_returns_json ( ) {
689- let ( bytes, content_type) = error_response_fallback_bytes ( & StdJsonSerialize ) ;
690- assert_eq ! ( content_type, "application/json" ) ;
691- let parsed: serde_json:: Value = serde_json:: from_slice ( & bytes) . unwrap ( ) ;
692- assert_eq ! ( parsed[ "id" ] , serde_json:: Value :: Null ) ;
693- assert_eq ! ( parsed[ "error" ] [ "code" ] , -32603 ) ;
694- }
695604}
0 commit comments