5757import uno .anahata .ai .tools .ToolManager ;
5858import uno .anahata .ai .internal .GsonUtils ;
5959import uno .anahata .ai .internal .PartUtils ;
60+ import uno .anahata .ai .swing .SwingChatConfig .UITheme ;
61+ import uno .anahata .ai .swing .render .PartType ;
6062
6163@ Slf4j
6264public class ContextHeatmapPanel extends JPanel {
@@ -68,7 +70,6 @@ public class ContextHeatmapPanel extends JPanel {
6870 private JLabel statusLabel ;
6971 private SwingWorker <List <PartInfo >, Void > worker ;
7072 private ToolManager toolManager ;
71- private SwingChatConfig .UITheme theme ;
7273
7374 private ScrollableTooltipPopup tooltipPopup ;
7475
@@ -78,7 +79,6 @@ public ContextHeatmapPanel() {
7879
7980 public void setToolManager (ToolManager toolManager ) {
8081 this .toolManager = toolManager ;
81- this .theme = new SwingChatConfig .UITheme ();
8282 }
8383
8484 private void initComponents () {
@@ -249,7 +249,7 @@ private List<PartInfo> buildPartInfoList(List<ChatMessage> context) {
249249 if (msg .getContent () != null && msg .getContent ().parts ().isPresent ()) {
250250 List <Part > parts = msg .getContent ().parts ().get ();
251251 for (int j = 0 ; j < parts .size (); j ++) {
252- infos .add (new PartInfo (i , j , msg , parts .get (j ), toolManager , theme , statusMap ));
252+ infos .add (new PartInfo (i , j , msg , parts .get (j ), toolManager , statusMap ));
253253 }
254254 }
255255 }
@@ -262,7 +262,7 @@ public static class PartInfo {
262262 private final int partIndex ;
263263 private final long messageSeqId ;
264264 private final String role ;
265- private final String partType ;
265+ private final PartType partType ;
266266 private final long sizeInBytes ;
267267 private final String functionName ;
268268 private final String resourceId ;
@@ -271,35 +271,30 @@ public static class PartInfo {
271271 private final String contentSummary ;
272272 private final String fullContentText ;
273273 private final boolean isError ;
274- private final Color roleColor ;
275274 private final Part part ;
276275
277- PartInfo (int msgIdx , int partIdx , ChatMessage msg , Part part , ToolManager fm , SwingChatConfig . UITheme theme , Map <String , ResourceStatus > statusMap ) {
276+ PartInfo (int msgIdx , int partIdx , ChatMessage msg , Part part , ToolManager fm , Map <String , ResourceStatus > statusMap ) {
278277 this .messageIndex = msgIdx ;
279278 this .partIndex = partIdx ;
280279 this .messageSeqId = msg .getSequentialId ();
281280 this .role = msg .getContent ().role ().orElse ("unknown" );
282281 this .sizeInBytes = PartUtils .calculateSizeInBytes (part );
283- this .roleColor = getRoleColor (theme , this .role );
284282 this .part = part ;
283+ this .partType = PartType .from (part );
285284
286- String tempPartType = "Unknown" ;
287285 String tempFullContent = part .toString ();
288286 String tempFuncName = "" ;
289287 String tempResourceId = "" ;
290288 ResourceStatus tempResourceStatus = null ;
291289 boolean tempIsError = false ;
292290
293291 if (part .text ().isPresent ()) {
294- tempPartType = "Text" ;
295292 tempFullContent = part .text ().get ();
296293 } else if (part .functionCall ().isPresent ()) {
297- tempPartType = "FunctionCall" ;
298294 tempFuncName = part .functionCall ().get ().name ().orElse ("" );
299295 tempFullContent = "Call: " + tempFuncName + "\n Args: " + part .functionCall ().get ().args ();
300296 } else if (part .functionResponse ().isPresent ()) {
301297 FunctionResponse fr = part .functionResponse ().get ();
302- tempPartType = "FunctionResponse" ;
303298 tempFuncName = fr .name ().orElse ("" );
304299 Map <String , Object > respMap = (Map <String , Object >) fr .response ().get ();
305300 tempFullContent = "Response: " + tempFuncName + "\n Content: " + respMap ;
@@ -316,11 +311,14 @@ public static class PartInfo {
316311 }
317312 }
318313 } else if (part .inlineData ().isPresent ()) {
319- tempPartType = "Blob" ;
320314 tempFullContent = "MIME Type: " + part .inlineData ().get ().mimeType ().orElse ("" ) + ", Size: " + sizeInBytes + " bytes" ;
315+ } else if (part .codeExecutionResult ().isPresent ()) {
316+ tempFullContent = part .codeExecutionResult ().get ().output ().orElse ("" );
317+ tempIsError = "ERROR" .equalsIgnoreCase (part .codeExecutionResult ().get ().outcome ().map (Object ::toString ).orElse ("" ));
318+ } else if (part .executableCode ().isPresent ()) {
319+ tempFullContent = part .executableCode ().get ().code ().orElse ("" );
321320 }
322321
323- this .partType = tempPartType ;
324322 this .fullContentText = tempFullContent ;
325323 this .functionName = tempFuncName ;
326324 this .resourceId = tempResourceId ;
@@ -338,15 +336,6 @@ private String extractFilename(String path) {
338336 return path ;
339337 }
340338 }
341-
342- private Color getRoleColor (SwingChatConfig .UITheme theme , String role ) {
343- switch (role ) {
344- case "user" : return theme .getUserHeaderBg ();
345- case "model" : return theme .getModelHeaderBg ();
346- case "tool" : return theme .getToolHeaderBg ();
347- default : return theme .getDefaultHeaderBg ();
348- }
349- }
350339 }
351340
352341 private static class PartTableModel extends AbstractTableModel {
@@ -381,7 +370,7 @@ public Object getValueAt(int rowIndex, int columnIndex) {
381370 case 0 : return info .getMessageIndex ();
382371 case 1 : return info .getPartIndex ();
383372 case 2 : return info .getRole ();
384- case 3 : return info .getPartType ();
373+ case 3 : return info .getPartType (). name () ;
385374 case 4 : return info .getSizeInBytes ();
386375 case 5 : return info .getFunctionName ();
387376 case 6 : return info .getResourceIdFilename ();
@@ -401,12 +390,13 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole
401390 if (!isSelected ) {
402391 int modelRow = table .convertRowIndexToModel (row );
403392 PartInfo info = tableModel .getPartInfo (modelRow );
393+ UITheme theme = UITheme .get ();
404394 if (info .isError ()) {
405- c .setBackground (theme .getFunctionErrorBg ());
406- c .setForeground (theme .getFunctionErrorFg ());
395+ c .setBackground (theme .getErrorBg ());
396+ c .setForeground (theme .getErrorFg ());
407397 } else {
408- c .setBackground (info .getRoleColor ( ));
409- c .setForeground (theme .getFontColor ( ));
398+ c .setBackground (theme . getHeatmapRowBg ( info .getRole () ));
399+ c .setForeground (theme .getHeatmapRowFg ( info . getRole () ));
410400 }
411401 }
412402 return c ;
@@ -418,15 +408,6 @@ private static class PieChartPanel extends JPanel {
418408 private final JTable table ;
419409 private final PartTableModel tableModel ;
420410 private static final DecimalFormat PERCENT_FORMAT = new DecimalFormat ("#.0%" );
421- private static final Map <String , Color > PART_TYPE_COLORS = new HashMap <>();
422-
423- static {
424- PART_TYPE_COLORS .put ("Text" , new Color (0 , 120 , 215 ));
425- PART_TYPE_COLORS .put ("FunctionCall" , new Color (216 , 59 , 1 ));
426- PART_TYPE_COLORS .put ("FunctionResponse" , new Color (0 , 153 , 188 ));
427- PART_TYPE_COLORS .put ("Blob" , new Color (104 , 33 , 122 ));
428- PART_TYPE_COLORS .put ("Unknown" , Color .GRAY );
429- }
430411
431412 public PieChartPanel (JTable table , PartTableModel tableModel ) {
432413 this .table = table ;
@@ -497,9 +478,10 @@ private void processData(List<PartInfo> data) {
497478 }
498479 List <Slice > newSlices = new ArrayList <>();
499480 double currentAngle = 0 ;
481+ UITheme theme = UITheme .get ();
500482 for (PartInfo info : data ) {
501483 double angle = (double ) info .getSizeInBytes () / totalSize * 360.0 ;
502- Color color = PART_TYPE_COLORS . getOrDefault (info .getPartType (), Color . DARK_GRAY );
484+ Color color = theme . getPieColor (info .getRole (), info . isError () );
503485 newSlices .add (new Slice (currentAngle , angle , color , info , (double ) info .getSizeInBytes () / totalSize ));
504486 currentAngle += angle ;
505487 }
@@ -569,7 +551,8 @@ private void drawLabels(Graphics2D g2d, List<LabelInfo> labels, FontMetrics fm)
569551 adjustLabelPositions (leftLabels , fm );
570552
571553 // Draw all labels and lines
572- g2d .setColor (Color .BLACK );
554+ UITheme theme = UITheme .get ();
555+ g2d .setColor (theme .getFontColor ());
573556 for (LabelInfo label : labels ) {
574557 g2d .drawLine ((int ) label .edgePoint .getX (), (int ) label .edgePoint .getY (), (int ) label .leaderLineEnd .getX (), (int ) label .leaderLineEnd .getY ());
575558 g2d .drawLine ((int ) label .leaderLineEnd .getX (), (int ) label .leaderLineEnd .getY (), (int ) label .horizontalLineEnd .getX (), (int ) label .horizontalLineEnd .getY ());
@@ -598,7 +581,7 @@ public String getToolTipText(MouseEvent e) {
598581 if (slice != null ) {
599582 PartInfo info = slice .info ;
600583 return String .format ("<html><b>%s</b> (Msg %d, Part %d)<br>Size: %d bytes (%.2f%%)<br>Type: %s<br>Summary: %s</html>" ,
601- info .getRole (), info .getMessageIndex (), info .getPartIndex (), info .getSizeInBytes (), slice .percentage * 100 , info .getPartType (), info .getContentSummary ());
584+ info .getRole (), info .getMessageIndex (), info .getPartIndex (), info .getSizeInBytes (), slice .percentage * 100 , info .getPartType (). name () , info .getContentSummary ());
602585 }
603586 return null ;
604587 }
@@ -622,10 +605,19 @@ private static class LabelInfo {
622605
623606 LabelInfo (Slice slice , double midAngleRad , int diameter , double sliceCenterX , double sliceCenterY ) {
624607 this .midAngleRad = midAngleRad ;
625- this .text = String .format ("%s (%s)" ,
626- slice .info .getResourceIdFilename ().isEmpty () ? slice .info .getPartType () : slice .info .getResourceIdFilename (),
627- PERCENT_FORMAT .format (slice .percentage )
628- );
608+
609+ String gist ;
610+ if (!slice .info .getResourceIdFilename ().isEmpty ()) {
611+ gist = slice .info .getResourceIdFilename ();
612+ } else if (slice .info .getPartType () == PartType .TEXT ) {
613+ gist = StringUtils .capitalize (slice .info .getRole ());
614+ } else if (slice .info .getPartType () == PartType .FUNCTION_CALL || slice .info .getPartType () == PartType .FUNCTION_RESPONSE ) {
615+ gist = slice .info .getFunctionName ();
616+ } else {
617+ gist = slice .info .getPartType ().name ();
618+ }
619+
620+ this .text = String .format ("%s (%s)" , gist , PERCENT_FORMAT .format (slice .percentage ));
629621
630622 double radius = diameter / 2.0 ;
631623 double labelRadius = radius + 15 ;
@@ -665,4 +657,4 @@ void adjustY(double amount) {
665657 }
666658 }
667659 }
668- }
660+ }
0 commit comments