From a68d6fd41914139d55d836607773011f73b4736d Mon Sep 17 00:00:00 2001 From: Mahesh Kommareddi Date: Wed, 17 Jul 2024 04:12:16 -0400 Subject: [PATCH] Lots of bug squashing --- src/main/java/com/ioa/IoASystem.java | 22 ++++++-- .../com/ioa/conversation/ConversationFSM.java | 19 +++++-- .../java/com/ioa/conversation/Message.java | 9 ++++ .../com/ioa/service/WebSocketService.java | 51 ++++++++++++++++-- target/classes/com/ioa/IoASystem.class | Bin 11505 -> 11715 bytes ...versationFSM$ConversationStateUpdate.class | Bin 1115 -> 1115 bytes .../ioa/conversation/ConversationFSM.class | Bin 8549 -> 8766 bytes .../com/ioa/conversation/Message.class | Bin 771 -> 1390 bytes .../com/ioa/service/WebSocketService.class | Bin 1621 -> 3342 bytes 9 files changed, 90 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/ioa/IoASystem.java b/src/main/java/com/ioa/IoASystem.java index c775c23..940fd7f 100644 --- a/src/main/java/com/ioa/IoASystem.java +++ b/src/main/java/com/ioa/IoASystem.java @@ -13,10 +13,26 @@ import com.ioa.model.BedrockLanguageModel; import com.ioa.service.WebSocketService; import com.ioa.util.TreeOfThought; +import com.ioa.tool.common.AppointmentSchedulerTool; +import com.ioa.tool.common.DistanceCalculatorTool; +import com.ioa.tool.common.FinancialAdviceTool; +import com.ioa.tool.common.FitnessClassFinderTool; +import com.ioa.tool.common.MovieRecommendationTool; +import com.ioa.tool.common.NewsUpdateTool; +import com.ioa.tool.common.PriceComparisonTool; +import com.ioa.tool.common.RecipeTool; +import com.ioa.tool.common.ReminderTool; +import com.ioa.tool.common.RestaurantFinderTool; +import com.ioa.tool.common.TranslationTool; +import com.ioa.tool.common.TravelBookingTool; +import com.ioa.tool.common.WeatherTool; +import com.ioa.tool.common.WebSearchTool; + import org.springframework.context.ConfigurableApplicationContext; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Lazy; import org.springframework.messaging.simp.SimpMessagingTemplate; import java.util.Arrays; @@ -26,12 +42,12 @@ import java.util.List; public class IoASystem { @Bean - public WebSocketService webSocketService(SimpMessagingTemplate messagingTemplate) { - return new WebSocketService(messagingTemplate); + public WebSocketService webSocketService(SimpMessagingTemplate messagingTemplate, @Lazy ConversationManager conversationManager) { + return new WebSocketService(messagingTemplate, conversationManager); } @Bean - public ConversationManager conversationManager(BedrockLanguageModel model, WebSocketService webSocketService) { + public ConversationManager conversationManager(BedrockLanguageModel model, @Lazy WebSocketService webSocketService) { return new ConversationManager(model, webSocketService); } diff --git a/src/main/java/com/ioa/conversation/ConversationFSM.java b/src/main/java/com/ioa/conversation/ConversationFSM.java index 2048686..1547e48 100644 --- a/src/main/java/com/ioa/conversation/ConversationFSM.java +++ b/src/main/java/com/ioa/conversation/ConversationFSM.java @@ -61,10 +61,23 @@ public class ConversationFSM { } private void handleMessage(Message message) { - if (message.getContent().startsWith("/vote")) { + if (message == null) { + System.out.println("DEBUG: Received null message"); + return; + } + + String content = message.getContent(); + if (content == null) { + System.out.println("DEBUG: Message content is null"); + return; + } + + System.out.println("DEBUG: Received message: " + content); + + if (content.startsWith("/vote")) { handleVote(message.getSender()); } else { - String stateTransitionTask = "Decide the next conversation state based on this message: " + message.getContent() + + String stateTransitionTask = "Decide the next conversation state based on this message: " + content + "\nCurrent state: " + currentState + "\nParticipants: " + participants + "\nPossible states: " + Arrays.toString(ConversationState.values()); @@ -86,7 +99,7 @@ public class ConversationFSM { agent.receiveMessage(message); } } - + webSocketService.sendUpdate("conversation_message", message); } } diff --git a/src/main/java/com/ioa/conversation/Message.java b/src/main/java/com/ioa/conversation/Message.java index 1e02b49..48567dc 100644 --- a/src/main/java/com/ioa/conversation/Message.java +++ b/src/main/java/com/ioa/conversation/Message.java @@ -22,4 +22,13 @@ public class Message { public String getContent() { return content; } + + @Override + public String toString() { + return "Message{" + + "conversationId='" + conversationId + '\'' + + ", sender='" + sender + '\'' + + ", content='" + content + '\'' + + '}'; + } } \ No newline at end of file diff --git a/src/main/java/com/ioa/service/WebSocketService.java b/src/main/java/com/ioa/service/WebSocketService.java index a4ee469..a593391 100644 --- a/src/main/java/com/ioa/service/WebSocketService.java +++ b/src/main/java/com/ioa/service/WebSocketService.java @@ -1,21 +1,62 @@ package com.ioa.service; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.JsonNode; +import com.ioa.conversation.ConversationManager; +import com.ioa.conversation.Message; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.stereotype.Service; +import org.springframework.context.annotation.Lazy; @Service public class WebSocketService { private final SimpMessagingTemplate messagingTemplate; + private final ConversationManager conversationManager; + private final ObjectMapper objectMapper; - public WebSocketService(SimpMessagingTemplate messagingTemplate) { + @Autowired + public WebSocketService(SimpMessagingTemplate messagingTemplate, @Lazy ConversationManager conversationManager) { this.messagingTemplate = messagingTemplate; + this.conversationManager = conversationManager; + this.objectMapper = new ObjectMapper(); } public void sendUpdate(String topic, Object payload) { - if (payload != null) { - messagingTemplate.convertAndSend("/topic/" + topic, payload); - } else { - System.out.println("Warning: Attempted to send null payload to topic: " + topic); + messagingTemplate.convertAndSend("/topic/" + topic, payload); + } + + public void handleWebSocketMessage(String message) { + System.out.println("DEBUG: Received WebSocket message: " + message); + + // Parse the WebSocket frame + String[] parts = message.split("\n\n", 2); + if (parts.length < 2) { + System.out.println("DEBUG: Invalid WebSocket message format"); + return; + } + + String headers = parts[0]; + String payload = parts[1]; + + // Parse the JSON payload + try { + JsonNode jsonNode = objectMapper.readTree(payload); + + // Extract relevant information from the JSON + // Adjust this based on the actual structure of your WebSocket messages + String conversationId = jsonNode.path("conversationId").asText(); + String sender = jsonNode.path("sender").asText(); + String content = jsonNode.path("content").asText(); + + // Create a new Message object + Message parsedMessage = new Message(conversationId, sender, content); + + // Process the message + conversationManager.postMessage(conversationId, sender, content); + } catch (Exception e) { + System.out.println("DEBUG: Error parsing WebSocket message: " + e.getMessage()); + e.printStackTrace(); } } } \ No newline at end of file diff --git a/target/classes/com/ioa/IoASystem.class b/target/classes/com/ioa/IoASystem.class index 3c4d13cc2cda5efaf87f9c6c361dc2b64169953e..df0d0f8d7b89344d00225cd2da29a16c9d0bfe51 100644 GIT binary patch delta 1560 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 delta 2893 zcmY*b3w)E+75|?!$(MY&O-q_K{o2w7kkY1wf>0i%JPHhHr91^eK@8yo3MH*gio8ZZ z2lB82UPQn-!Qt3|O&$_y-9X*k!};37ZEWo6*n4wqLpOBbxnDx5za;mbd+xdC@jvI@ zlk<}89X)wUKkBT~u^HP0wqrIyUuMQ9wnXD*H15Jqf}?76OWf4afyXrL z64;GB@&m25Tng+}@@|%&ZAO=vZ92TzC-5ZpvzF!I=#pl0E+3U+wF1$Bg97vL6rr?C zUhx|8q{AVvyER>hA5RN>0nf<&u2G)Dcviy~1&-i3dCAq_0*(rN8DEi4X+?6ddy(fj zPH6b5z}N7+Jm_BKBb-tK&nx3+1YW>dY3K`_FAAJPr(CbsIbRa^I=&%a)l1zM@Un(i z1YVU_^nS}P;9CN(VH3d~HP^&dh~E+TE*c3=^MUqob40(~V!_HyVB`@H@OG&pU@?`e4Il z755()P+6z>zG&rAkZ8gL`pB zA^$Hzep&g{72(z4s`hwObJfI_=4LaZVjAtie{fa92Ld1BzjA>X@3-Tcz(@F41!BhH zgkV{@3}^WZX0(}0nj+!2$%n4vhDH!XWFrLRrmTRxDkcxXb+QX`5If?Cw6sV0bVgZu zg9r8G667YGmByOZnHIa=MM5@b78zbaS*oU-OPiuivE@2OQ7=J0%8`dN3!Dy|a#5aq zC9|L?pWypcMq+VxN23BltvuxIBlEo_<m*saTHj4)z!n6mU=W4=U??PW@UoPDa0O!TU(pg5=yLid*^VJR4Hg64Ptj!g7c_!K$`7;Z>@|W$pQ+8h&nA!f=Fq$|*L>qhYbLZzG9&Ve zzeFbd(1+U-fP|+I_;!KHR=%b80|WejIU13aCt-q-m_*&Zk2B z+mf;i&~E0rdFOaV5|8+HB=P70ctgB+Jc%ccVxMA%UVw292Y4F9(>Z+p91eBiOF$#D ziYh6IW77sIc0%z_0yTEEVc6A9jU!|@k~m%C3>nTOl1fV_x(GFzp>^Us;Q$6G>YId@ zF}=oRxRRKba^Tws;Wk`MfA8pxcllt@_XaN(pJIPANZ~aB**uPi;LHawF~NzN%+O82 zI5aSODjG2j^DzTq%)~O>g>9I_ZDKB-=7;VO?!hrEut1w_d-iE*)pcACybWMe%m zX$DgntZ5<5WXjI^X3{LC9IUmTW+R`|zyLDLiBvrtPhoE%J`|3?4L0P`;MK5MLr0IV zU&93;bPcu}oCI4+gmu|eH&Ll&`Xa9!JddsLy_Li}jg{x^M{rxE{q`h&oWxHR@IOCU zV?T{w4eUzb_dpVVJdK=_%&6$X-@4aaF#!~!2$#~>m0EdU1P%8ilS2t0!n;dQ43leQ zDF&elHCSQ6GmKp*MmF6=a~OaC0yNhGh283|%ds?T6f=nxj-b0~9$#8ja)m0mBG|3q zIy9Qk@q;v6y2kg@rh2wj!*3NAC;qMyYqJuYx(HFe1TDxxYmbZI?>6YCdn|i4)nL+S zJ;a%^v6kUnE!Ca)C!rJnCUoI{VCw%ibW#RkTWz6LhQzJH(R>7YD2F`B1ZCc;EFZ@S z#884bBhk(!@n8=phNqnbsARFV#-XIi&&HSJ(zclHP+cr&dD1g$&851eY3JStOnvmxbv zAN9;o-%cv!q|yLRDpjycRMknuEDT(5jW$$lw;dhv&y>FYSZz33~-9 A2mk;8 diff --git a/target/classes/com/ioa/conversation/Message.class b/target/classes/com/ioa/conversation/Message.class index e65d262d2d0cc53fe5cd4735e3492c8e0d798bae..7ea1be20ebc168649cb5d86b01c09cde3265b14f 100644 GIT binary patch literal 1390 zcmbVLZBG+H5Pp`HURw`ZN(E6wP>@ny&bKe7XrfJsn4%v_@PnV0>!utWyX0;mA;$mV z&(K6-!UunVKgu|JcY%{$h%wFH%uZ*Xd1hwk*YES60AAr~8AHff$lDl3fuXw3Pq^cA z*>~RW?h98l6xKcI>6Z+-#?np+MU*U*ZQOv(Fzu>C$5Y&Kl{^ta$hD`Wvn9fi_XWdf z+Pv9gsC6#!yE^b>zhw|dZBz_gAr!JF0%IDpQ8OlsAheLWMs({oZeoIA@{k{hwvsN_ zA3VKBTBy0yA;a6oV1j?KEDbs_JpW&?9fo{c^{4@rjwi*tJ6jB6eW9t^i%y%C)*G4ROXS*(y2((E!%Q0)idw~;Cwo^N2d>!g z3^6;I+M1aVJ%rav=}-s!XiMll)eDPw$nY$2`b1Mnv3Rk_7FTBD;l(=rZ_=5|=Sl&M zGM3P^uxuu{!Z3gN3_N+F4ulhPqT*<%8{E|@IA!>fo9!^iZSMPBPYW7_y(y&#+CC3M5n6B<76xj{qH5tW4f=Xl zT7t*!(enK>3fTAK6&R!)|)@Tn#*Ufnk#1*X|A53 z`i<;En4<3lMSzg=DABKsQNkW4wA*BD#__m=X}S?ol$S-C$!yrv&1w=ShP#+aGCL%V z*KqSYtgocRsS1&?5<%OsLjuikFEe=LYVdew@N8yq^=j~BX7Joa@Oo4Rwbjt3GeW0& nPTjy&r0En=EvX@g`%$G2Fi)~b^)1p_z$)F!q^;o*o?z+^@Z&o! delta 283 zcmaFI)y&3q>ff$?3=9m84Du7XRrQGb?kmFfcN(G6(}nk;zw?RT)Jm|7Mov7Xuoo#lQk2MHs{x zBqpn}D6>m4NP$)PvxwD;0%h2MJO&1S29R1FFq;*m7RX~{kcOxQvh{&HkUCbaEeyOH efD9%Egl1u^nq{zR7C_Rh1U6C}t8Q7a9dZElJ|cer diff --git a/target/classes/com/ioa/service/WebSocketService.class b/target/classes/com/ioa/service/WebSocketService.class index cbdc7d77b55fd6badd9a25f6d480315a35e5039e..8918a6b6ba7f0ce95eb91d6732151602941b7332 100644 GIT binary patch literal 3342 zcmbVOYjYDv7CmiQ9$6VM2ty*m5@ARzKVT9kyMPQyj01^@3LFCaZc46HK~a zPRq~<-Fm|*v6=nfwUZ`*oi+xrOJGmM_tsPpO6~gItn}of3Is-rTS2u?JJX%ElNK@p zW5#?zhFS&d^_sIRD=VSzIaR6Uyz5nC9A;&sp@KAaBVj_=YhxcC6|nsXrRJ=_(P;07 zbT*k`39>f!<8gsU>vBag#){NeUA@F!sHLYvfv57t2Sq7qgW2Rr=TI8I!9fd8*vR3K zz=>aru)xkHZhFeAmXuc&7;cZCNsGz00OAotj>9-&;Yk}$VR##tN*jc?P73*}WYpf~ zV%K*rF&oXCl&ljCfovM17_%^L<0y`?!cpei4FxPi99{G1sXekSY|1G-Ezpxrr!j$N zEj(xAxA@)mcp?}Dl3}CfGNODJKQklO+mei(r*MLJyma==m6r>-8E;M2+-j~x`dpL3 zD!1SVb*T+o3N|KjN+87?t8;-O`%ib-Y~+`SbDo^M;8)dT3OtH&iJHuxsiyHFrYxMX zF>Ur5{sl&F`4Z@DNWElMpS5ugFY~a=a89igk->Zyj-@a|laQoPK?<+35~PY&p0+S6 zaG>kCYaU^hMiCc{$XpUQ*#&@3s5?hS%4u9i$-yA7-ovQFi!w+>Fi-oIO z)QXhu?0Q8tjE1C9#x)ziH%O!x)s}sR8cAlB@kbkfGAcO`5wN5w6?1{Cu%?UoUoUA7 zuU8{wmTa0VUP}T$7JHsUXIVEz{4M7fgKGQgsR$dbFfvTrv5e$w-e7ZXTels>D*3R z&RO;7rlduZZq2o^r;B>gZizC)E0fzt^yS4BF~!0aW*v6J;gTN1R20Y$`o!U$Dfj;~rjSumWg^$hk`U$srP;b{;^H&&VbOlf=c;lXH zGFaf7c4dkUo3XzV6+b*u^!=69M*H>GNw{qb=ZHxc^Y-d&5wwkzv5RS0tCd`>2&O&b zc`BH$$uLx*h0g_^?8vEGs208yIQaifDeBF`3I6UMy$3Nmb{E#@_+9K6{T{oo-NT-{7`(&T9!R$PxDMEZUJRlid$E%v zS^AvkXs+o66;$~}f6?wD>Y4p}pxE!@6JdeBi~R35VG0IdS{KV~-(df>IG};i?_iDH z$78_wCJsD^!aR75|DAZeZRdg3&I4FMjn2Tl>+onT;Nw`+z4)3rq&au{TMW^A9@xal zSjI_i;+fg;ACmus&6&(`j@}thOk5c6ohbA&l)-H8CQcTT*<|MQCSKUYONBo6Uy1t` z`{(0+>U$KgW&5&LHgyjd3jJKYqxrds*Zzh5g(P>#a>Li}<9f8e`S`;fMmUZexXF7e z5#fEFwF3^aiie2!5OY4v_6XZy{^e;sj^lWmZ-!@Zkx!-Td?qd91bv*Mmy@`K0zT#I z_zO{(#&dX{NcC}T9y9D&^l$*LvX`Qt9S9Jz&bL@;jn%03w_7OR z##)5(Al~MF>qL2&xNmSQ!KfC9e2qN0$@qtm_zwW(8JJ;4^%|?6Us_F9(*h delta 559 zcmX|8%TC)s6g^{1>^Q~&H-U!oFe#5TNlDv4fl%6}1y*#yL$E_~gH>4s+iE7Ltmqe1 zMe`4^1yn%Fq7oYxY*F|9f>!;3ifdC<*4%r~nS1V;@qFq1p=;NFTi*dxv3Q^zYbKS3 zjwCw8SGJHaaZf=?M;hJYC;ODRkBov|9S_haYSN@(Xc&a0U`R(655=K0Ei=sJ4n9}J zMf;|>j5UmoRc_a|-`T;M{l4yqlseX*S!sIQ-Er34hD%)4^L%b|*Y_F>q)m%uHMc&+ zpq98FxU~{fF~d;aus?dP_n~4{Id^sf?rd4yw;GPOWqHkd-3sizx^G8hq^npg8N;lG z7noDvcVS4ic*K`FHM z(E$|C(RGC6DS8Sm^aJM@2+i6Mnwew+x`vESdJ+>uNJWO$-KhVDSrqY@jA%T@QKI8K rp<0HNPEdSGwS;FVQ;t#B1m#Iug9gzRBA!Qa8n21e2v_kI3&`98ab{b}