@@ -44,7 +44,6 @@ const handleSubmitFeedback = async (
4444
4545const handleSendDrugSummary = async ( message : FormValues [ "message" ] , guid : string ) => {
4646 try {
47-
4847 const endpoint = guid ? `/v1/api/embeddings/ask_embeddings?guid=${ guid } ` : '/v1/api/embeddings/ask_embeddings' ;
4948 const response = await api . post ( endpoint , {
5049 message,
@@ -57,6 +56,117 @@ const handleSendDrugSummary = async (message: FormValues["message"], guid: strin
5756 }
5857} ;
5958
59+ interface StreamCallbacks {
60+ onContent ?: ( content : string ) => void ;
61+ onComplete ?: ( data : { embeddings_info : any [ ] ; done : boolean } ) => void ;
62+ onError ?: ( error : string ) => void ;
63+ onMetadata ?: ( data : { question : string ; embeddings_count : number } ) => void ;
64+ }
65+
66+ const handleSendDrugSummaryStream = async (
67+ message : string ,
68+ guid : string ,
69+ callbacks : StreamCallbacks
70+ ) : Promise < void > => {
71+ const token = localStorage . getItem ( "access" ) ;
72+ const endpoint = `/v1/api/embeddings/ask_embeddings?stream=true${
73+ guid ? `&guid=${ guid } ` : ""
74+ } `;
75+
76+ try {
77+ const response = await fetch ( baseURL + endpoint , {
78+ method : "POST" ,
79+ headers : {
80+ "Content-Type" : "application/json" ,
81+ Authorization : `JWT ${ token } ` ,
82+ } ,
83+ body : JSON . stringify ( { message } ) ,
84+ } ) ;
85+
86+ if ( ! response . ok ) {
87+ throw new Error ( `HTTP error! status: ${ response . status } ` ) ;
88+ }
89+
90+ if ( ! response . body ) {
91+ throw new Error ( "No response body" ) ;
92+ }
93+
94+ const reader = response . body . getReader ( ) ;
95+ const decoder = new TextDecoder ( "utf-8" ) ;
96+ let buffer = "" ;
97+
98+ // eslint-disable-next-line no-constant-condition
99+ while ( true ) {
100+ const { done, value } = await reader . read ( ) ;
101+ if ( done ) break ;
102+
103+ const chunk = decoder . decode ( value , { stream : true } ) ;
104+ buffer += chunk ;
105+
106+ const lines = buffer . split ( "\n" ) ;
107+ buffer = lines . pop ( ) || "" ; // Save incomplete line
108+
109+ for ( const line of lines ) {
110+ if ( ! line . trim ( ) . startsWith ( "data: " ) ) continue ;
111+
112+ const jsonStr = line . slice ( 6 ) . trim ( ) ;
113+ if ( ! jsonStr ) continue ;
114+
115+ try {
116+ const data = JSON . parse ( jsonStr ) ;
117+
118+ if ( data . content ) {
119+ callbacks . onContent ?.( data . content ) ;
120+ } else if ( data . done ) {
121+ callbacks . onComplete ?.( { embeddings_info : [ ] , done : true } ) ;
122+ } else if ( data . error ) {
123+ callbacks . onError ?.( data . error ) ;
124+ } else if ( data . type ) {
125+ switch ( data . type ) {
126+ case "metadata" :
127+ callbacks . onMetadata ?.( {
128+ question : data . question ,
129+ embeddings_count : data . embeddings_count ,
130+ } ) ;
131+ break ;
132+ case "content" :
133+ callbacks . onContent ?.( data . content ) ;
134+ break ;
135+ case "complete" :
136+ callbacks . onComplete ?.( data ) ;
137+ break ;
138+ case "error" :
139+ callbacks . onError ?.( data . error ) ;
140+ break ;
141+ }
142+ }
143+ } catch ( parseError ) {
144+ console . error ( "Failed to parse SSE data:" , parseError , "Raw line:" , line ) ;
145+ }
146+ }
147+ }
148+ } catch ( error ) {
149+ const errorMessage = error instanceof Error ? error . message : "Unknown error" ;
150+ console . error ( "Error in stream:" , errorMessage ) ;
151+ callbacks . onError ?.( errorMessage ) ;
152+ throw error ;
153+ }
154+ } ;
155+
156+
157+ // Legacy function for backward compatibility
158+ const handleSendDrugSummaryStreamLegacy = async (
159+ message : string ,
160+ guid : string ,
161+ onChunk : ( chunk : string ) => void ,
162+ ) : Promise < void > => {
163+ return handleSendDrugSummaryStream ( message , guid , {
164+ onContent : onChunk ,
165+ onError : ( error ) => console . error ( "Stream error:" , error ) ,
166+ onComplete : ( ) => console . log ( "Stream completed" )
167+ } ) ;
168+ } ;
169+
60170const fetchConversations = async ( ) : Promise < Conversation [ ] > => {
61171 try {
62172 const response = await api . get ( `/chatgpt/conversations/` ) ;
@@ -143,4 +253,6 @@ export {
143253 continueConversation ,
144254 deleteConversation ,
145255 updateConversationTitle ,
146- } ;
256+ handleSendDrugSummaryStream ,
257+ handleSendDrugSummaryStreamLegacy
258+ } ;
0 commit comments