abstractassistant 0.3.3__py3-none-any.whl → 0.3.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -186,8 +186,8 @@ class ProviderManager:
186
186
  Returns:
187
187
  Formatted display name
188
188
  """
189
- # Extract the last part of the model name (after /)
190
- display_name = model.split('/')[-1] if '/' in model else model
189
+ # Use the full model name (preserving provider prefix)
190
+ display_name = model
191
191
 
192
192
  # Truncate if too long
193
193
  if len(display_name) > max_length:
@@ -405,6 +405,7 @@ class QtChatBubble(QWidget):
405
405
  ("Clear", self.clear_session),
406
406
  ("Load", self.load_session),
407
407
  ("Save", self.save_session),
408
+ # ("Compact", self.compact_session), # Hidden for now - functionality preserved
408
409
  ("History", self.show_history)
409
410
  ]
410
411
 
@@ -614,6 +615,7 @@ class QtChatBubble(QWidget):
614
615
  self.model_combo.currentTextChanged.connect(self.on_model_changed)
615
616
  self.model_combo.setFixedHeight(28)
616
617
  self.model_combo.setMinimumWidth(140)
618
+ self.model_combo.view().setMinimumWidth(380) # Wider dropdown to show full model names
617
619
  self.model_combo.setStyleSheet("""
618
620
  QComboBox {
619
621
  background: rgba(255, 255, 255, 0.08);
@@ -769,39 +771,38 @@ class QtChatBubble(QWidget):
769
771
  }
770
772
 
771
773
  QComboBox QAbstractItemView {
772
- background: #1a202c;
773
- border: 1px solid #4a5568;
774
+ background: #252525;
775
+ border: 1px solid #404040;
774
776
  border-radius: 8px;
775
- selection-background-color: #4299e1;
776
- color: #e2e8f0;
777
- padding: 4px;
778
- font-family: "Helvetica Neue", "Helvetica", "Segoe UI", Arial, sans-serif;
777
+ selection-background-color: #404040;
778
+ color: #ffffff;
779
+ padding: 6px;
780
+ font-family: "SF Mono", "Monaco", "Menlo", "Consolas", monospace;
779
781
  }
780
-
782
+
781
783
  QComboBox QAbstractItemView::item {
782
- height: 36px;
783
- padding: 8px 12px;
784
+ height: 44px;
785
+ padding: 10px 16px;
784
786
  border: none;
785
- font-size: 12px;
786
- font-weight: 400; /* Changed from 500 to 400 (normal weight) */
787
- color: #e2e8f0;
788
- border-radius: 4px;
789
- margin: 2px;
787
+ font-size: 13px;
788
+ font-weight: 400;
789
+ color: #e8e8e8;
790
+ border-radius: 6px;
791
+ margin: 3px;
792
+ letter-spacing: 0.02em;
790
793
  }
791
-
794
+
792
795
  QComboBox QAbstractItemView::item:selected {
793
- background: #4299e1;
796
+ background: #404040;
794
797
  color: #ffffff;
798
+ font-weight: 500;
799
+ border: 1px solid #0066cc;
795
800
  }
796
-
801
+
797
802
  QComboBox QAbstractItemView::item:hover {
798
- background: #374151;
803
+ background: #333333;
799
804
  }
800
805
 
801
- QComboBox QAbstractItemView::item:selected {
802
- background: #4299e1;
803
- }
804
-
805
806
  /* Labels - Clean Typography */
806
807
  QLabel {
807
808
  color: rgba(255, 255, 255, 0.8);
@@ -985,7 +986,7 @@ class QtChatBubble(QWidget):
985
986
 
986
987
  # Add models to dropdown with display names
987
988
  for model in models:
988
- display_name = self.provider_manager.create_model_display_name(model, max_length=25)
989
+ display_name = self.provider_manager.create_model_display_name(model, max_length=55)
989
990
  self.model_combo.addItem(display_name, model)
990
991
 
991
992
  # Set preferred model
@@ -1013,9 +1014,10 @@ class QtChatBubble(QWidget):
1013
1014
  models = get_available_models_for_provider(self.current_provider)
1014
1015
 
1015
1016
  for model in models:
1016
- display_name = model.split('/')[-1] if '/' in model else model
1017
- if len(display_name) > 25:
1018
- display_name = display_name[:22] + "..."
1017
+ # Use full model name (preserving provider prefix)
1018
+ display_name = model
1019
+ if len(display_name) > 55:
1020
+ display_name = display_name[:52] + "..."
1019
1021
  self.model_combo.addItem(display_name, model)
1020
1022
 
1021
1023
  if self.model_combo.count() > 0:
@@ -1971,6 +1973,268 @@ class QtChatBubble(QWidget):
1971
1973
  if self.debug:
1972
1974
  print("🧹 Session cleared (including attached files and file tracking)")
1973
1975
 
1976
+ def compact_session(self):
1977
+ """Compact the current session using AbstractCore's summarizer functionality."""
1978
+ if not self.message_history:
1979
+ QMessageBox.information(
1980
+ self,
1981
+ "No Session",
1982
+ "No conversation history to compact. Start a conversation first."
1983
+ )
1984
+ return
1985
+
1986
+ # Check if session is too short to compact
1987
+ if len(self.message_history) < 4: # Need at least 2 exchanges to be worth compacting
1988
+ QMessageBox.information(
1989
+ self,
1990
+ "Session Too Short",
1991
+ "Session is too short to compact. Need at least 2 exchanges (4 messages)."
1992
+ )
1993
+ return
1994
+
1995
+ reply = QMessageBox.question(
1996
+ self,
1997
+ "Compact Session",
1998
+ "This will summarize the conversation history into a concise system message, "
1999
+ "keeping only the most recent 2 exchanges for context.\n\n"
2000
+ "This action cannot be undone. Continue?",
2001
+ QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
2002
+ QMessageBox.StandardButton.No
2003
+ )
2004
+
2005
+ if reply == QMessageBox.StandardButton.Yes:
2006
+ try:
2007
+ # Show progress
2008
+ self.status_label.setText("compacting")
2009
+ self.status_label.setStyleSheet("""
2010
+ QLabel {
2011
+ background: rgba(250, 179, 135, 0.2);
2012
+ border: 1px solid rgba(250, 179, 135, 0.3);
2013
+ border-radius: 12px;
2014
+ padding: 4px 12px;
2015
+ font-size: 11px;
2016
+ font-weight: 600;
2017
+ text-transform: uppercase;
2018
+ letter-spacing: 0.5px;
2019
+ color: #fab387;
2020
+ }
2021
+ """)
2022
+
2023
+ # Notify main app about status change
2024
+ if self.status_callback:
2025
+ self.status_callback("compacting")
2026
+
2027
+ # Create conversation text for summarization
2028
+ conversation_text = self._format_conversation_for_summarization()
2029
+
2030
+ # Use AbstractCore's summarizer functionality through LLMManager
2031
+ summary = self._generate_conversation_summary(conversation_text)
2032
+
2033
+ if summary:
2034
+ # Keep the last 2 exchanges (4 messages) for context
2035
+ recent_messages = self.message_history[-4:] if len(self.message_history) >= 4 else self.message_history[-2:]
2036
+
2037
+ # Create new session with summary as system context
2038
+ self._create_compacted_session(summary, recent_messages)
2039
+
2040
+ # Update UI
2041
+ self.token_count = 0 # Reset token count
2042
+ self.update_token_display()
2043
+
2044
+ # Show success message
2045
+ QMessageBox.information(
2046
+ self,
2047
+ "Session Compacted",
2048
+ f"Session successfully compacted!\n\n"
2049
+ f"Original: {len(self.message_history)} messages\n"
2050
+ f"Compacted: Summary + {len(recent_messages)} recent messages"
2051
+ )
2052
+
2053
+ if self.debug:
2054
+ print(f"🗜️ Session compacted: {len(self.message_history)} -> summary + {len(recent_messages)} recent")
2055
+ else:
2056
+ raise Exception("Failed to generate summary")
2057
+
2058
+ except Exception as e:
2059
+ QMessageBox.critical(
2060
+ self,
2061
+ "Compaction Error",
2062
+ f"Failed to compact session:\n{str(e)}"
2063
+ )
2064
+ if self.debug:
2065
+ print(f"❌ Failed to compact session: {e}")
2066
+ import traceback
2067
+ traceback.print_exc()
2068
+ finally:
2069
+ # Reset status
2070
+ self.status_label.setText("ready")
2071
+ self.status_label.setStyleSheet("""
2072
+ QLabel {
2073
+ background: rgba(166, 227, 161, 0.2);
2074
+ border: 1px solid rgba(166, 227, 161, 0.3);
2075
+ border-radius: 12px;
2076
+ padding: 4px 12px;
2077
+ font-size: 11px;
2078
+ font-weight: 600;
2079
+ text-transform: uppercase;
2080
+ letter-spacing: 0.5px;
2081
+ color: #a6e3a1;
2082
+ }
2083
+ """)
2084
+ if self.status_callback:
2085
+ self.status_callback("ready")
2086
+
2087
+ def _format_conversation_for_summarization(self) -> str:
2088
+ """Format the conversation history for summarization."""
2089
+ lines = []
2090
+ lines.append("=== CONVERSATION HISTORY ===\n")
2091
+
2092
+ for i, msg in enumerate(self.message_history):
2093
+ role = "USER" if msg.get('type') == 'user' else "ASSISTANT"
2094
+ content = msg.get('content', '')
2095
+ timestamp = msg.get('timestamp', '')
2096
+
2097
+ # Add timestamp if available
2098
+ if timestamp:
2099
+ try:
2100
+ from datetime import datetime
2101
+ if isinstance(timestamp, str):
2102
+ dt = datetime.fromisoformat(timestamp)
2103
+ time_str = dt.strftime("%Y-%m-%d %H:%M")
2104
+ lines.append(f"[{time_str}] {role}:")
2105
+ else:
2106
+ lines.append(f"{role}:")
2107
+ except:
2108
+ lines.append(f"{role}:")
2109
+ else:
2110
+ lines.append(f"{role}:")
2111
+
2112
+ lines.append(content)
2113
+ lines.append("") # Empty line between messages
2114
+
2115
+ return "\n".join(lines)
2116
+
2117
+ def _generate_conversation_summary(self, conversation_text: str) -> str:
2118
+ """Generate a conversation summary using AbstractCore's summarizer functionality."""
2119
+ try:
2120
+ # Use the current LLM to generate a summary
2121
+ # This mimics what the AbstractCore summarizer CLI does
2122
+ summary_prompt = f"""Please provide a comprehensive but concise summary of the following conversation.
2123
+ Focus on:
2124
+ - Key topics discussed
2125
+ - Important decisions or conclusions reached
2126
+ - Relevant context that should be preserved
2127
+ - Any ongoing tasks or questions
2128
+
2129
+ The summary should be detailed enough to provide context for continuing the conversation, but concise enough to save tokens.
2130
+
2131
+ Conversation to summarize:
2132
+ {conversation_text}
2133
+
2134
+ Please provide the summary in a clear, structured format:"""
2135
+
2136
+ if self.llm_manager and self.llm_manager.llm:
2137
+ # Generate summary using current LLM
2138
+ response = self.llm_manager.llm.generate(summary_prompt)
2139
+
2140
+ if hasattr(response, 'content'):
2141
+ return response.content
2142
+ else:
2143
+ return str(response)
2144
+ else:
2145
+ raise Exception("No LLM available for summarization")
2146
+
2147
+ except Exception as e:
2148
+ if self.debug:
2149
+ print(f"❌ Error generating summary: {e}")
2150
+ raise
2151
+
2152
+ def _create_compacted_session(self, summary: str, recent_messages: list):
2153
+ """Create a new session with the summary and recent messages."""
2154
+ try:
2155
+ # Create new session with summary embedded in the system prompt.
2156
+ final_system_prompt = f"""You are a helpful AI assistant who has access to tools to help the user.
2157
+ Always be a critical and creative thinker who leverage constructive skepticism to progress and evolve its reasoning and answers.
2158
+ Always answer in nicely formatted markdown.
2159
+
2160
+ === CONVERSATION CONTEXT ===
2161
+ The following is a summary of our previous conversation:
2162
+
2163
+ {summary}
2164
+
2165
+ === END CONTEXT ===
2166
+
2167
+ Continue the conversation naturally, referring to the context above when relevant."""
2168
+
2169
+ # Create new session with the composed system prompt
2170
+ if self.llm_manager:
2171
+ # Create new session with custom system prompt
2172
+ from abstractcore import BasicSession
2173
+
2174
+ # Prepare tools list (same as in LLMManager)
2175
+ tools = []
2176
+ try:
2177
+ from abstractcore.tools.common_tools import (
2178
+ list_files, search_files, read_file, edit_file,
2179
+ write_file, execute_command, web_search
2180
+ )
2181
+ tools = [
2182
+ list_files, search_files, read_file, edit_file,
2183
+ write_file, execute_command, web_search
2184
+ ]
2185
+ except ImportError:
2186
+ pass
2187
+
2188
+ # Create new session with summary in system prompt
2189
+ new_session = BasicSession(
2190
+ self.llm_manager.llm,
2191
+ system_prompt=final_system_prompt,
2192
+ tools=tools
2193
+ )
2194
+
2195
+ # Add recent messages to the new session
2196
+ for msg in recent_messages:
2197
+ if msg.get('type') == 'user':
2198
+ # Add user message without generating response
2199
+ from abstractcore.messages import UserMessage
2200
+ user_msg = UserMessage(content=msg.get('content', ''))
2201
+ new_session.messages.append(user_msg)
2202
+ elif msg.get('type') == 'assistant':
2203
+ # Add assistant message
2204
+ from abstractcore.messages import AssistantMessage
2205
+ assistant_msg = AssistantMessage(content=msg.get('content', ''))
2206
+ new_session.messages.append(assistant_msg)
2207
+
2208
+ # Replace current session
2209
+ self.llm_manager.current_session = new_session
2210
+
2211
+ # Update local message history to reflect the compacted state
2212
+ # Create a special "system" message to represent the summary
2213
+ compacted_history = [
2214
+ {
2215
+ 'timestamp': datetime.now().isoformat(),
2216
+ 'type': 'system',
2217
+ 'content': f"📋 **Session Compacted**\n\n{summary}",
2218
+ 'provider': self.current_provider,
2219
+ 'model': self.current_model,
2220
+ 'attached_files': []
2221
+ }
2222
+ ]
2223
+
2224
+ # Add recent messages
2225
+ compacted_history.extend(recent_messages)
2226
+
2227
+ # Update message history
2228
+ self.message_history = compacted_history
2229
+
2230
+ if self.debug:
2231
+ print(f"✅ Created compacted session with enhanced system prompt")
2232
+
2233
+ except Exception as e:
2234
+ if self.debug:
2235
+ print(f"❌ Error creating compacted session: {e}")
2236
+ raise
2237
+
1974
2238
  def load_session(self):
1975
2239
  """Load a session using AbstractCore via LLMManager."""
1976
2240
  file_path, _ = QFileDialog.getOpenFileName(
@@ -2192,8 +2456,12 @@ class QtChatBubble(QWidget):
2192
2456
  # Toggle behavior: create dialog if doesn't exist, toggle visibility if it does
2193
2457
  if iPhoneMessagesDialog:
2194
2458
  if self.history_dialog is None:
2195
- # Create dialog first time
2196
- self.history_dialog = iPhoneMessagesDialog.create_dialog(self.message_history, self)
2459
+ # Create dialog first time with deletion support
2460
+ self.history_dialog = iPhoneMessagesDialog.create_dialog(
2461
+ self.message_history,
2462
+ self,
2463
+ delete_callback=self._handle_message_deletion
2464
+ )
2197
2465
  # Set callback to update button when dialog is hidden via Back button
2198
2466
  self.history_dialog.set_hide_callback(lambda: self._update_history_button_appearance(False))
2199
2467
  self.history_dialog.show()
@@ -2205,7 +2473,11 @@ class QtChatBubble(QWidget):
2205
2473
  self._update_history_button_appearance(False)
2206
2474
  else:
2207
2475
  # Update dialog with latest messages before showing
2208
- self.history_dialog = iPhoneMessagesDialog.create_dialog(self.message_history, self)
2476
+ self.history_dialog = iPhoneMessagesDialog.create_dialog(
2477
+ self.message_history,
2478
+ self,
2479
+ delete_callback=self._handle_message_deletion
2480
+ )
2209
2481
  # Set callback to update button when dialog is hidden via Back button
2210
2482
  self.history_dialog.set_hide_callback(lambda: self._update_history_button_appearance(False))
2211
2483
  self.history_dialog.show()
@@ -2256,6 +2528,159 @@ class QtChatBubble(QWidget):
2256
2528
  }
2257
2529
  """)
2258
2530
 
2531
+ def _handle_message_deletion(self, indices_to_delete: List[int]):
2532
+ """Handle deletion of messages from the history dialog."""
2533
+ try:
2534
+ if not indices_to_delete:
2535
+ return
2536
+
2537
+ # Validate indices
2538
+ for index in indices_to_delete:
2539
+ if not (0 <= index < len(self.message_history)):
2540
+ QMessageBox.critical(
2541
+ self,
2542
+ "Invalid Selection",
2543
+ f"Invalid message index {index}. Please refresh and try again."
2544
+ )
2545
+ return
2546
+
2547
+ # Delete messages from local history (indices are sorted in reverse order)
2548
+ original_count = len(self.message_history)
2549
+
2550
+ for index in indices_to_delete:
2551
+ if 0 <= index < len(self.message_history):
2552
+ del self.message_history[index]
2553
+
2554
+ # Update AbstractCore session to reflect deletions
2555
+ self._update_abstractcore_session_after_deletion()
2556
+
2557
+ # Update token count
2558
+ self._update_token_count_from_session()
2559
+
2560
+ # Update history dialog if it's open (keep it open!)
2561
+ if self.history_dialog and self.history_dialog.isVisible():
2562
+ try:
2563
+ # Update the dialog content without closing it
2564
+ self.history_dialog.update_message_history(self.message_history)
2565
+ except Exception as dialog_error:
2566
+ import traceback
2567
+ traceback.print_exc()
2568
+ # Fallback: recreate dialog if update fails
2569
+ try:
2570
+ if len(self.message_history) == 0:
2571
+ self.history_dialog.hide()
2572
+ self._update_history_button_appearance(False)
2573
+ else:
2574
+ new_dialog = iPhoneMessagesDialog.create_dialog(
2575
+ self.message_history,
2576
+ self,
2577
+ delete_callback=self._handle_message_deletion
2578
+ )
2579
+ if new_dialog:
2580
+ old_pos = self.history_dialog.pos()
2581
+ self.history_dialog.hide()
2582
+ self.history_dialog = new_dialog
2583
+ self.history_dialog.move(old_pos) # Keep same position
2584
+ self.history_dialog.set_hide_callback(lambda: self._update_history_button_appearance(False))
2585
+ self.history_dialog.show()
2586
+ except:
2587
+ try:
2588
+ self.history_dialog.hide()
2589
+ self._update_history_button_appearance(False)
2590
+ except:
2591
+ pass
2592
+
2593
+ # Log success (no popup)
2594
+ deleted_count = original_count - len(self.message_history)
2595
+
2596
+ if self.debug:
2597
+ print(f"🗑️ Deleted {deleted_count} messages from history")
2598
+
2599
+ except Exception as e:
2600
+ print(f"❌ Critical error in _handle_message_deletion: {e}")
2601
+ import traceback
2602
+ traceback.print_exc()
2603
+
2604
+ try:
2605
+ QMessageBox.critical(
2606
+ self,
2607
+ "Deletion Error",
2608
+ f"Failed to delete messages:\n{str(e)}\n\nCheck console for details."
2609
+ )
2610
+ except:
2611
+ print("❌ Could not show error dialog")
2612
+
2613
+ if self.debug:
2614
+ print(f"❌ Failed to delete messages: {e}")
2615
+ import traceback
2616
+ traceback.print_exc()
2617
+
2618
+ def _update_abstractcore_session_after_deletion(self):
2619
+ """Update AbstractCore session to reflect message deletions."""
2620
+ try:
2621
+ if not self.llm_manager or not self.llm_manager.current_session:
2622
+ return
2623
+
2624
+ # Get current system prompt
2625
+ current_session = self.llm_manager.current_session
2626
+ system_prompt = getattr(current_session, 'system_prompt', None) or """
2627
+ You are a helpful AI assistant who has access to tools to help the user.
2628
+ Always be a critical and creative thinker who leverage constructive skepticism to progress and evolve its reasoning and answers.
2629
+ Always answer in nicely formatted markdown.
2630
+ """
2631
+
2632
+ # Prepare tools list (same as in LLMManager)
2633
+ tools = []
2634
+ try:
2635
+ from abstractcore.tools.common_tools import (
2636
+ list_files, search_files, read_file, edit_file,
2637
+ write_file, execute_command, web_search
2638
+ )
2639
+ tools = [
2640
+ list_files, search_files, read_file, edit_file,
2641
+ write_file, execute_command, web_search
2642
+ ]
2643
+ except ImportError as import_error:
2644
+ pass
2645
+ pass
2646
+
2647
+ # Create new session with updated message history
2648
+ from abstractcore import BasicSession
2649
+ new_session = BasicSession(
2650
+ self.llm_manager.llm,
2651
+ system_prompt=system_prompt,
2652
+ tools=tools
2653
+ )
2654
+
2655
+ # Add remaining messages to the new session
2656
+ for i, msg in enumerate(self.message_history):
2657
+ try:
2658
+ if msg.get('type') == 'user':
2659
+ from abstractcore.messages import UserMessage
2660
+ user_msg = UserMessage(content=msg.get('content', ''))
2661
+ new_session.messages.append(user_msg)
2662
+ elif msg.get('type') == 'assistant':
2663
+ from abstractcore.messages import AssistantMessage
2664
+ assistant_msg = AssistantMessage(content=msg.get('content', ''))
2665
+ new_session.messages.append(assistant_msg)
2666
+ elif msg.get('type') == 'system':
2667
+ # Skip system messages (handled by system_prompt)
2668
+ pass
2669
+ else:
2670
+ # Unknown message type
2671
+ pass
2672
+ except Exception as msg_error:
2673
+ # Continue with other messages
2674
+ pass
2675
+
2676
+ # Replace current session
2677
+ self.llm_manager.current_session = new_session
2678
+
2679
+ except Exception as e:
2680
+ import traceback
2681
+ traceback.print_exc()
2682
+ # Don't raise - this is not critical for the UI operation
2683
+
2259
2684
  def close_app(self):
2260
2685
  """Close the entire application completely."""
2261
2686
  if self.debug:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: abstractassistant
3
- Version: 0.3.3
3
+ Version: 0.3.5
4
4
  Summary: A sleek (macOS) system tray application providing instant access to LLMs
5
5
  Author-email: Laurent-Philippe Albou <contact@abstractcore.ai>
6
6
  License-Expression: MIT
@@ -21,14 +21,14 @@ Classifier: Topic :: Desktop Environment
21
21
  Requires-Python: >=3.9
22
22
  Description-Content-Type: text/markdown
23
23
  License-File: LICENSE
24
- Requires-Dist: abstractcore[all]>=2.5.0
24
+ Requires-Dist: abstractcore[anthropic,lmstudio,ollama,openai,tools]>=2.9.1
25
25
  Requires-Dist: pystray>=0.19.4
26
26
  Requires-Dist: Pillow>=10.0.0
27
27
  Requires-Dist: PyQt5>=5.15.0
28
28
  Requires-Dist: markdown>=3.5.0
29
29
  Requires-Dist: pygments>=2.16.0
30
30
  Requires-Dist: pymdown-extensions>=10.0
31
- Requires-Dist: abstractvoice>=0.5.1
31
+ Requires-Dist: abstractvoice>=0.5.2
32
32
  Requires-Dist: pyperclip>=1.8.2
33
33
  Requires-Dist: plyer>=2.1.0
34
34
  Requires-Dist: tomli>=2.0.0; python_version < "3.11"
@@ -9,9 +9,9 @@ abstractassistant/core/llm_manager.py,sha256=hJun-nDfRv9zxv_3tfrHAmVYSYT96E-0zDJ
9
9
  abstractassistant/core/tts_manager.py,sha256=Cxh302EgIycwkWxe7XntmLW-j_WusbJOYRCs3Jms3CU,9892
10
10
  abstractassistant/ui/__init__.py,sha256=aRNE2pS50nFAX6y--rSGMNYwhz905g14gRd6g4BolYU,13
11
11
  abstractassistant/ui/chat_bubble.py,sha256=bY48b4IeQzOrRN2_sJ5OazhZcJ8IMaBM6R3EexvU30Q,11885
12
- abstractassistant/ui/history_dialog.py,sha256=949l8fVgRpUfRGcoOVRutERVXrShYgpKkFJCxo2JG-4,19323
13
- abstractassistant/ui/provider_manager.py,sha256=9IM-BxIs6lUlk6cDCBi7oZFMXmn4CFMlxh0s-_vhzXY,8403
14
- abstractassistant/ui/qt_bubble.py,sha256=ujJtoDuVuXthxfXsvHX-YbqV4GuUgNp2FGy_wT3t4UY,96990
12
+ abstractassistant/ui/history_dialog.py,sha256=lVyNrZVu73CZo593DvnuWU1iCpmZybTCFTjlu4RrqBM,39701
13
+ abstractassistant/ui/provider_manager.py,sha256=v61bM3yNt5jEbU5yS6J2q32kl6qw8zG-I6vKtx3l0cA,8364
14
+ abstractassistant/ui/qt_bubble.py,sha256=sPeL54bIVVDUsE51U2b_XgtzDVIb-qbkI1IHz26dLlw,115631
15
15
  abstractassistant/ui/toast_manager.py,sha256=1aU4DPo-J45bC61gTEctHq98ZrHIFxRfZa_9Q8KF588,13721
16
16
  abstractassistant/ui/toast_window.py,sha256=BRSwEBlaND5LLipn1HOX0ISWxVH-zOHsYplFkiPaj_g,21727
17
17
  abstractassistant/ui/tts_state_manager.py,sha256=UF_zrfl9wf0hNHBGxevcoKxW5Dh7zXibUSVoSSjGP4o,10565
@@ -19,9 +19,9 @@ abstractassistant/ui/ui_styles.py,sha256=FvE2CVUbHmHu1PKVTBBGyhbt781qh4WjLMrHvil
19
19
  abstractassistant/utils/__init__.py,sha256=7Q3BxyXETkt3tm5trhuLTyL8PoECOK0QiK-0KUVAR2Q,16
20
20
  abstractassistant/utils/icon_generator.py,sha256=SWPgi1V6_8544Zbc2vAfFXAy15H35neyUGCYt2eKoic,16475
21
21
  abstractassistant/utils/markdown_renderer.py,sha256=u5tVIhulSwRYADiqJcZNoHhU8e6pJVgzrwZRd61Bov0,12585
22
- abstractassistant-0.3.3.dist-info/licenses/LICENSE,sha256=QUjFNAE-0yOkW9-Rle2axkpkt9H7xiZ2VbN-VeONhxc,1106
23
- abstractassistant-0.3.3.dist-info/METADATA,sha256=gHXdK078vCVh3vMAdjAxEd32JPShNpV3DCkNWLlUjZ0,11564
24
- abstractassistant-0.3.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
- abstractassistant-0.3.3.dist-info/entry_points.txt,sha256=MIzeCh0XG6MbhIzBHtkdEjmjxYBsQrGFevq8Y1L8Jkc,118
26
- abstractassistant-0.3.3.dist-info/top_level.txt,sha256=qZc_LQH3CBxLq2P4B1aHayzkj8hn0euR31edkXQVzDA,18
27
- abstractassistant-0.3.3.dist-info/RECORD,,
22
+ abstractassistant-0.3.5.dist-info/licenses/LICENSE,sha256=QUjFNAE-0yOkW9-Rle2axkpkt9H7xiZ2VbN-VeONhxc,1106
23
+ abstractassistant-0.3.5.dist-info/METADATA,sha256=T58ZbA3OYjIjS9qm1EPaLOMPqcwFrezy4o1-HZYTrUg,11599
24
+ abstractassistant-0.3.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
+ abstractassistant-0.3.5.dist-info/entry_points.txt,sha256=MIzeCh0XG6MbhIzBHtkdEjmjxYBsQrGFevq8Y1L8Jkc,118
26
+ abstractassistant-0.3.5.dist-info/top_level.txt,sha256=qZc_LQH3CBxLq2P4B1aHayzkj8hn0euR31edkXQVzDA,18
27
+ abstractassistant-0.3.5.dist-info/RECORD,,