abstractassistant 0.3.2__py3-none-any.whl → 0.3.4__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.
@@ -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
 
@@ -1070,13 +1071,15 @@ class QtChatBubble(QWidget):
1070
1071
 
1071
1072
  # Check for Enter/Return key
1072
1073
  if event.key() == Qt.Key.Key_Return or event.key() == Qt.Key.Key_Enter:
1073
- # Shift+Enter or Ctrl+Enter or Cmd+Enter should send message
1074
- if (event.modifiers() & Qt.KeyboardModifier.ShiftModifier or
1075
- event.modifiers() & Qt.KeyboardModifier.ControlModifier or
1076
- event.modifiers() & Qt.KeyboardModifier.MetaModifier):
1074
+ # Shift+Enter should add a new line
1075
+ if event.modifiers() & Qt.KeyboardModifier.ShiftModifier:
1076
+ # Allow default behavior (new line)
1077
+ QTextEdit.keyPressEvent(self.input_text, event)
1078
+ return
1079
+ # Plain Enter should send message
1080
+ else:
1077
1081
  self.send_message()
1078
1082
  return
1079
- # Plain Enter should add a new line (default behavior)
1080
1083
 
1081
1084
  # Call original keyPressEvent for all other keys
1082
1085
  QTextEdit.keyPressEvent(self.input_text, event)
@@ -1969,6 +1972,268 @@ class QtChatBubble(QWidget):
1969
1972
  if self.debug:
1970
1973
  print("🧹 Session cleared (including attached files and file tracking)")
1971
1974
 
1975
+ def compact_session(self):
1976
+ """Compact the current session using AbstractCore's summarizer functionality."""
1977
+ if not self.message_history:
1978
+ QMessageBox.information(
1979
+ self,
1980
+ "No Session",
1981
+ "No conversation history to compact. Start a conversation first."
1982
+ )
1983
+ return
1984
+
1985
+ # Check if session is too short to compact
1986
+ if len(self.message_history) < 4: # Need at least 2 exchanges to be worth compacting
1987
+ QMessageBox.information(
1988
+ self,
1989
+ "Session Too Short",
1990
+ "Session is too short to compact. Need at least 2 exchanges (4 messages)."
1991
+ )
1992
+ return
1993
+
1994
+ reply = QMessageBox.question(
1995
+ self,
1996
+ "Compact Session",
1997
+ "This will summarize the conversation history into a concise system message, "
1998
+ "keeping only the most recent 2 exchanges for context.\n\n"
1999
+ "This action cannot be undone. Continue?",
2000
+ QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
2001
+ QMessageBox.StandardButton.No
2002
+ )
2003
+
2004
+ if reply == QMessageBox.StandardButton.Yes:
2005
+ try:
2006
+ # Show progress
2007
+ self.status_label.setText("compacting")
2008
+ self.status_label.setStyleSheet("""
2009
+ QLabel {
2010
+ background: rgba(250, 179, 135, 0.2);
2011
+ border: 1px solid rgba(250, 179, 135, 0.3);
2012
+ border-radius: 12px;
2013
+ padding: 4px 12px;
2014
+ font-size: 11px;
2015
+ font-weight: 600;
2016
+ text-transform: uppercase;
2017
+ letter-spacing: 0.5px;
2018
+ color: #fab387;
2019
+ }
2020
+ """)
2021
+
2022
+ # Notify main app about status change
2023
+ if self.status_callback:
2024
+ self.status_callback("compacting")
2025
+
2026
+ # Create conversation text for summarization
2027
+ conversation_text = self._format_conversation_for_summarization()
2028
+
2029
+ # Use AbstractCore's summarizer functionality through LLMManager
2030
+ summary = self._generate_conversation_summary(conversation_text)
2031
+
2032
+ if summary:
2033
+ # Keep the last 2 exchanges (4 messages) for context
2034
+ recent_messages = self.message_history[-4:] if len(self.message_history) >= 4 else self.message_history[-2:]
2035
+
2036
+ # Create new session with summary as system context
2037
+ self._create_compacted_session(summary, recent_messages)
2038
+
2039
+ # Update UI
2040
+ self.token_count = 0 # Reset token count
2041
+ self.update_token_display()
2042
+
2043
+ # Show success message
2044
+ QMessageBox.information(
2045
+ self,
2046
+ "Session Compacted",
2047
+ f"Session successfully compacted!\n\n"
2048
+ f"Original: {len(self.message_history)} messages\n"
2049
+ f"Compacted: Summary + {len(recent_messages)} recent messages"
2050
+ )
2051
+
2052
+ if self.debug:
2053
+ print(f"🗜️ Session compacted: {len(self.message_history)} -> summary + {len(recent_messages)} recent")
2054
+ else:
2055
+ raise Exception("Failed to generate summary")
2056
+
2057
+ except Exception as e:
2058
+ QMessageBox.critical(
2059
+ self,
2060
+ "Compaction Error",
2061
+ f"Failed to compact session:\n{str(e)}"
2062
+ )
2063
+ if self.debug:
2064
+ print(f"❌ Failed to compact session: {e}")
2065
+ import traceback
2066
+ traceback.print_exc()
2067
+ finally:
2068
+ # Reset status
2069
+ self.status_label.setText("ready")
2070
+ self.status_label.setStyleSheet("""
2071
+ QLabel {
2072
+ background: rgba(166, 227, 161, 0.2);
2073
+ border: 1px solid rgba(166, 227, 161, 0.3);
2074
+ border-radius: 12px;
2075
+ padding: 4px 12px;
2076
+ font-size: 11px;
2077
+ font-weight: 600;
2078
+ text-transform: uppercase;
2079
+ letter-spacing: 0.5px;
2080
+ color: #a6e3a1;
2081
+ }
2082
+ """)
2083
+ if self.status_callback:
2084
+ self.status_callback("ready")
2085
+
2086
+ def _format_conversation_for_summarization(self) -> str:
2087
+ """Format the conversation history for summarization."""
2088
+ lines = []
2089
+ lines.append("=== CONVERSATION HISTORY ===\n")
2090
+
2091
+ for i, msg in enumerate(self.message_history):
2092
+ role = "USER" if msg.get('type') == 'user' else "ASSISTANT"
2093
+ content = msg.get('content', '')
2094
+ timestamp = msg.get('timestamp', '')
2095
+
2096
+ # Add timestamp if available
2097
+ if timestamp:
2098
+ try:
2099
+ from datetime import datetime
2100
+ if isinstance(timestamp, str):
2101
+ dt = datetime.fromisoformat(timestamp)
2102
+ time_str = dt.strftime("%Y-%m-%d %H:%M")
2103
+ lines.append(f"[{time_str}] {role}:")
2104
+ else:
2105
+ lines.append(f"{role}:")
2106
+ except:
2107
+ lines.append(f"{role}:")
2108
+ else:
2109
+ lines.append(f"{role}:")
2110
+
2111
+ lines.append(content)
2112
+ lines.append("") # Empty line between messages
2113
+
2114
+ return "\n".join(lines)
2115
+
2116
+ def _generate_conversation_summary(self, conversation_text: str) -> str:
2117
+ """Generate a conversation summary using AbstractCore's summarizer functionality."""
2118
+ try:
2119
+ # Use the current LLM to generate a summary
2120
+ # This mimics what the AbstractCore summarizer CLI does
2121
+ summary_prompt = f"""Please provide a comprehensive but concise summary of the following conversation.
2122
+ Focus on:
2123
+ - Key topics discussed
2124
+ - Important decisions or conclusions reached
2125
+ - Relevant context that should be preserved
2126
+ - Any ongoing tasks or questions
2127
+
2128
+ The summary should be detailed enough to provide context for continuing the conversation, but concise enough to save tokens.
2129
+
2130
+ Conversation to summarize:
2131
+ {conversation_text}
2132
+
2133
+ Please provide the summary in a clear, structured format:"""
2134
+
2135
+ if self.llm_manager and self.llm_manager.llm:
2136
+ # Generate summary using current LLM
2137
+ response = self.llm_manager.llm.generate(summary_prompt)
2138
+
2139
+ if hasattr(response, 'content'):
2140
+ return response.content
2141
+ else:
2142
+ return str(response)
2143
+ else:
2144
+ raise Exception("No LLM available for summarization")
2145
+
2146
+ except Exception as e:
2147
+ if self.debug:
2148
+ print(f"❌ Error generating summary: {e}")
2149
+ raise
2150
+
2151
+ def _create_compacted_session(self, summary: str, recent_messages: list):
2152
+ """Create a new session with the summary and recent messages."""
2153
+ try:
2154
+ # Create new session with summary as enhanced system prompt
2155
+ enhanced_system_prompt = f"""You are a helpful AI assistant who has access to tools to help the user.
2156
+ Always be a critical and creative thinker who leverage constructive skepticism to progress and evolve its reasoning and answers.
2157
+ Always answer in nicely formatted markdown.
2158
+
2159
+ === CONVERSATION CONTEXT ===
2160
+ The following is a summary of our previous conversation:
2161
+
2162
+ {summary}
2163
+
2164
+ === END CONTEXT ===
2165
+
2166
+ Continue the conversation naturally, referring to the context above when relevant."""
2167
+
2168
+ # Create new session with enhanced system prompt
2169
+ if self.llm_manager:
2170
+ # Create new session with custom system prompt
2171
+ from abstractcore import BasicSession
2172
+
2173
+ # Prepare tools list (same as in LLMManager)
2174
+ tools = []
2175
+ try:
2176
+ from abstractcore.tools.common_tools import (
2177
+ list_files, search_files, read_file, edit_file,
2178
+ write_file, execute_command, web_search
2179
+ )
2180
+ tools = [
2181
+ list_files, search_files, read_file, edit_file,
2182
+ write_file, execute_command, web_search
2183
+ ]
2184
+ except ImportError:
2185
+ pass
2186
+
2187
+ # Create new session with summary in system prompt
2188
+ new_session = BasicSession(
2189
+ self.llm_manager.llm,
2190
+ system_prompt=enhanced_system_prompt,
2191
+ tools=tools
2192
+ )
2193
+
2194
+ # Add recent messages to the new session
2195
+ for msg in recent_messages:
2196
+ if msg.get('type') == 'user':
2197
+ # Add user message without generating response
2198
+ from abstractcore.messages import UserMessage
2199
+ user_msg = UserMessage(content=msg.get('content', ''))
2200
+ new_session.messages.append(user_msg)
2201
+ elif msg.get('type') == 'assistant':
2202
+ # Add assistant message
2203
+ from abstractcore.messages import AssistantMessage
2204
+ assistant_msg = AssistantMessage(content=msg.get('content', ''))
2205
+ new_session.messages.append(assistant_msg)
2206
+
2207
+ # Replace current session
2208
+ self.llm_manager.current_session = new_session
2209
+
2210
+ # Update local message history to reflect the compacted state
2211
+ # Create a special "system" message to represent the summary
2212
+ compacted_history = [
2213
+ {
2214
+ 'timestamp': datetime.now().isoformat(),
2215
+ 'type': 'system',
2216
+ 'content': f"📋 **Session Compacted**\n\n{summary}",
2217
+ 'provider': self.current_provider,
2218
+ 'model': self.current_model,
2219
+ 'attached_files': []
2220
+ }
2221
+ ]
2222
+
2223
+ # Add recent messages
2224
+ compacted_history.extend(recent_messages)
2225
+
2226
+ # Update message history
2227
+ self.message_history = compacted_history
2228
+
2229
+ if self.debug:
2230
+ print(f"✅ Created compacted session with enhanced system prompt")
2231
+
2232
+ except Exception as e:
2233
+ if self.debug:
2234
+ print(f"❌ Error creating compacted session: {e}")
2235
+ raise
2236
+
1972
2237
  def load_session(self):
1973
2238
  """Load a session using AbstractCore via LLMManager."""
1974
2239
  file_path, _ = QFileDialog.getOpenFileName(
@@ -2190,8 +2455,12 @@ class QtChatBubble(QWidget):
2190
2455
  # Toggle behavior: create dialog if doesn't exist, toggle visibility if it does
2191
2456
  if iPhoneMessagesDialog:
2192
2457
  if self.history_dialog is None:
2193
- # Create dialog first time
2194
- self.history_dialog = iPhoneMessagesDialog.create_dialog(self.message_history, self)
2458
+ # Create dialog first time with deletion support
2459
+ self.history_dialog = iPhoneMessagesDialog.create_dialog(
2460
+ self.message_history,
2461
+ self,
2462
+ delete_callback=self._handle_message_deletion
2463
+ )
2195
2464
  # Set callback to update button when dialog is hidden via Back button
2196
2465
  self.history_dialog.set_hide_callback(lambda: self._update_history_button_appearance(False))
2197
2466
  self.history_dialog.show()
@@ -2203,7 +2472,11 @@ class QtChatBubble(QWidget):
2203
2472
  self._update_history_button_appearance(False)
2204
2473
  else:
2205
2474
  # Update dialog with latest messages before showing
2206
- self.history_dialog = iPhoneMessagesDialog.create_dialog(self.message_history, self)
2475
+ self.history_dialog = iPhoneMessagesDialog.create_dialog(
2476
+ self.message_history,
2477
+ self,
2478
+ delete_callback=self._handle_message_deletion
2479
+ )
2207
2480
  # Set callback to update button when dialog is hidden via Back button
2208
2481
  self.history_dialog.set_hide_callback(lambda: self._update_history_button_appearance(False))
2209
2482
  self.history_dialog.show()
@@ -2254,6 +2527,159 @@ class QtChatBubble(QWidget):
2254
2527
  }
2255
2528
  """)
2256
2529
 
2530
+ def _handle_message_deletion(self, indices_to_delete: List[int]):
2531
+ """Handle deletion of messages from the history dialog."""
2532
+ try:
2533
+ if not indices_to_delete:
2534
+ return
2535
+
2536
+ # Validate indices
2537
+ for index in indices_to_delete:
2538
+ if not (0 <= index < len(self.message_history)):
2539
+ QMessageBox.critical(
2540
+ self,
2541
+ "Invalid Selection",
2542
+ f"Invalid message index {index}. Please refresh and try again."
2543
+ )
2544
+ return
2545
+
2546
+ # Delete messages from local history (indices are sorted in reverse order)
2547
+ original_count = len(self.message_history)
2548
+
2549
+ for index in indices_to_delete:
2550
+ if 0 <= index < len(self.message_history):
2551
+ del self.message_history[index]
2552
+
2553
+ # Update AbstractCore session to reflect deletions
2554
+ self._update_abstractcore_session_after_deletion()
2555
+
2556
+ # Update token count
2557
+ self._update_token_count_from_session()
2558
+
2559
+ # Update history dialog if it's open (keep it open!)
2560
+ if self.history_dialog and self.history_dialog.isVisible():
2561
+ try:
2562
+ # Update the dialog content without closing it
2563
+ self.history_dialog.update_message_history(self.message_history)
2564
+ except Exception as dialog_error:
2565
+ import traceback
2566
+ traceback.print_exc()
2567
+ # Fallback: recreate dialog if update fails
2568
+ try:
2569
+ if len(self.message_history) == 0:
2570
+ self.history_dialog.hide()
2571
+ self._update_history_button_appearance(False)
2572
+ else:
2573
+ new_dialog = iPhoneMessagesDialog.create_dialog(
2574
+ self.message_history,
2575
+ self,
2576
+ delete_callback=self._handle_message_deletion
2577
+ )
2578
+ if new_dialog:
2579
+ old_pos = self.history_dialog.pos()
2580
+ self.history_dialog.hide()
2581
+ self.history_dialog = new_dialog
2582
+ self.history_dialog.move(old_pos) # Keep same position
2583
+ self.history_dialog.set_hide_callback(lambda: self._update_history_button_appearance(False))
2584
+ self.history_dialog.show()
2585
+ except:
2586
+ try:
2587
+ self.history_dialog.hide()
2588
+ self._update_history_button_appearance(False)
2589
+ except:
2590
+ pass
2591
+
2592
+ # Log success (no popup)
2593
+ deleted_count = original_count - len(self.message_history)
2594
+
2595
+ if self.debug:
2596
+ print(f"🗑️ Deleted {deleted_count} messages from history")
2597
+
2598
+ except Exception as e:
2599
+ print(f"❌ Critical error in _handle_message_deletion: {e}")
2600
+ import traceback
2601
+ traceback.print_exc()
2602
+
2603
+ try:
2604
+ QMessageBox.critical(
2605
+ self,
2606
+ "Deletion Error",
2607
+ f"Failed to delete messages:\n{str(e)}\n\nCheck console for details."
2608
+ )
2609
+ except:
2610
+ print("❌ Could not show error dialog")
2611
+
2612
+ if self.debug:
2613
+ print(f"❌ Failed to delete messages: {e}")
2614
+ import traceback
2615
+ traceback.print_exc()
2616
+
2617
+ def _update_abstractcore_session_after_deletion(self):
2618
+ """Update AbstractCore session to reflect message deletions."""
2619
+ try:
2620
+ if not self.llm_manager or not self.llm_manager.current_session:
2621
+ return
2622
+
2623
+ # Get current system prompt
2624
+ current_session = self.llm_manager.current_session
2625
+ system_prompt = getattr(current_session, 'system_prompt', None) or """
2626
+ You are a helpful AI assistant who has access to tools to help the user.
2627
+ Always be a critical and creative thinker who leverage constructive skepticism to progress and evolve its reasoning and answers.
2628
+ Always answer in nicely formatted markdown.
2629
+ """
2630
+
2631
+ # Prepare tools list (same as in LLMManager)
2632
+ tools = []
2633
+ try:
2634
+ from abstractcore.tools.common_tools import (
2635
+ list_files, search_files, read_file, edit_file,
2636
+ write_file, execute_command, web_search
2637
+ )
2638
+ tools = [
2639
+ list_files, search_files, read_file, edit_file,
2640
+ write_file, execute_command, web_search
2641
+ ]
2642
+ except ImportError as import_error:
2643
+ pass
2644
+ pass
2645
+
2646
+ # Create new session with updated message history
2647
+ from abstractcore import BasicSession
2648
+ new_session = BasicSession(
2649
+ self.llm_manager.llm,
2650
+ system_prompt=system_prompt,
2651
+ tools=tools
2652
+ )
2653
+
2654
+ # Add remaining messages to the new session
2655
+ for i, msg in enumerate(self.message_history):
2656
+ try:
2657
+ if msg.get('type') == 'user':
2658
+ from abstractcore.messages import UserMessage
2659
+ user_msg = UserMessage(content=msg.get('content', ''))
2660
+ new_session.messages.append(user_msg)
2661
+ elif msg.get('type') == 'assistant':
2662
+ from abstractcore.messages import AssistantMessage
2663
+ assistant_msg = AssistantMessage(content=msg.get('content', ''))
2664
+ new_session.messages.append(assistant_msg)
2665
+ elif msg.get('type') == 'system':
2666
+ # Skip system messages (handled by system_prompt)
2667
+ pass
2668
+ else:
2669
+ # Unknown message type
2670
+ pass
2671
+ except Exception as msg_error:
2672
+ # Continue with other messages
2673
+ pass
2674
+
2675
+ # Replace current session
2676
+ self.llm_manager.current_session = new_session
2677
+
2678
+ except Exception as e:
2679
+ import traceback
2680
+ traceback.print_exc()
2681
+ # Don't raise - this is not critical for the UI operation
2682
+
2257
2683
  def close_app(self):
2258
2684
  """Close the entire application completely."""
2259
2685
  if self.debug:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: abstractassistant
3
- Version: 0.3.2
3
+ Version: 0.3.4
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
@@ -211,26 +211,26 @@ assistant --debug
211
211
 
212
212
  ```
213
213
  abstractassistant/
214
- ├── pyproject.toml # Package configuration
215
- ├── requirements.txt # Dependencies
216
- ├── config.toml # Default configuration
217
- ├── abstractassistant/ # Main package
218
- │ ├── cli.py # CLI entry point
219
- │ ├── app.py # Main application
220
- │ ├── config.py # Configuration management
221
- │ ├── core/ # Business logic
222
- │ │ ├── llm_manager.py # LLM provider management
223
- │ │ └── tts_manager.py # Voice/TTS integration
224
- │ ├── ui/ # User interface
225
- │ │ ├── qt_bubble.py # Main Qt chat interface
226
- │ │ └── toast_window.py # Notification system
227
- │ └── utils/ # Utilities
228
- │ ├── icon_generator.py # Dynamic icon creation
229
- │ └── markdown_renderer.py # Markdown processing
230
- └── docs/ # Documentation
231
- ├── ARCHITECTURE.md # Technical documentation
232
- ├── INSTALLATION.md # Installation guide
233
- └── USAGE.md # Usage guide
214
+ ├── pyproject.toml # Package configuration
215
+ ├── requirements.txt # Dependencies
216
+ ├── config.toml # Default configuration
217
+ ├── abstractassistant/ # Main package
218
+ │ ├── cli.py # CLI entry point
219
+ │ ├── app.py # Main application
220
+ │ ├── config.py # Configuration management
221
+ │ ├── core/ # Business logic
222
+ │ │ ├── llm_manager.py # LLM provider management
223
+ │ │ └── tts_manager.py # Voice/TTS integration
224
+ │ ├── ui/ # User interface
225
+ │ │ ├── qt_bubble.py # Main Qt chat interface
226
+ │ │ └── toast_window.py # Notification system
227
+ │ └── utils/ # Utilities
228
+ │ ├── icon_generator.py # Dynamic icon creation
229
+ │ └── markdown_renderer.py # Markdown processing
230
+ └── docs/ # Documentation
231
+ ├── architecture.md # Technical documentation
232
+ ├── installation.md # Installation guide
233
+ └── getting-started.md # Usage guide
234
234
  ```
235
235
 
236
236
  ## 🌟 Why AbstractAssistant?
@@ -1,18 +1,17 @@
1
- setup_macos_app.py,sha256=9dIPr9TipjtgdIhd0MnR2syRNoFyBVMnRsWDW0UCT3A,10736
2
1
  abstractassistant/__init__.py,sha256=homfqMDh6sX2nBROtk6-y72jnrStPph8gEOeT0OjKyU,35
3
2
  abstractassistant/app.py,sha256=yGFszbaqja_Y1ejSMcVYIcq8f1qdeZpVTb032geI-ZE,40374
4
3
  abstractassistant/cli.py,sha256=SQPxQCLjX-LOlhSEvG302D0AOyxlxo5QM2imxr9wxmc,4385
5
4
  abstractassistant/config.py,sha256=KodfPYTpHtavJyne-h-B-r3kbEt1uusSY8GknGLtDL8,5809
6
- abstractassistant/create_app_bundle.py,sha256=LAZdp2C90ikMVd3KPdwNYBYUASbHpypOJIwvx6fQyXM,1698
5
+ abstractassistant/create_app_bundle.py,sha256=lJJsdnjl-WSdQVn8uFp7c_3cJkx8liZbK2C7elOCG1A,14215
7
6
  abstractassistant/web_server.py,sha256=_pqMzy13qfim9BMBqQJQifWyX7UQXFD_sZeiu4ZBt40,12816
8
7
  abstractassistant/core/__init__.py,sha256=TETStgToTe7QSsCZgRHDk2oSErlLJoeGN0sFg4Yx2_c,15
9
8
  abstractassistant/core/llm_manager.py,sha256=hJun-nDfRv9zxv_3tfrHAmVYSYT96E-0zDJB2TiaSeQ,19226
10
9
  abstractassistant/core/tts_manager.py,sha256=Cxh302EgIycwkWxe7XntmLW-j_WusbJOYRCs3Jms3CU,9892
11
10
  abstractassistant/ui/__init__.py,sha256=aRNE2pS50nFAX6y--rSGMNYwhz905g14gRd6g4BolYU,13
12
- abstractassistant/ui/chat_bubble.py,sha256=TE6zPtQ46I9grKGAb744wHqk4yO6-und3iif8_33XGk,11357
13
- abstractassistant/ui/history_dialog.py,sha256=949l8fVgRpUfRGcoOVRutERVXrShYgpKkFJCxo2JG-4,19323
11
+ abstractassistant/ui/chat_bubble.py,sha256=bY48b4IeQzOrRN2_sJ5OazhZcJ8IMaBM6R3EexvU30Q,11885
12
+ abstractassistant/ui/history_dialog.py,sha256=lVyNrZVu73CZo593DvnuWU1iCpmZybTCFTjlu4RrqBM,39701
14
13
  abstractassistant/ui/provider_manager.py,sha256=9IM-BxIs6lUlk6cDCBi7oZFMXmn4CFMlxh0s-_vhzXY,8403
15
- abstractassistant/ui/qt_bubble.py,sha256=cBjViRyusWWEmX5bHz4k-W8mUFRY6RPOuUq5AyN7ciI,97030
14
+ abstractassistant/ui/qt_bubble.py,sha256=kCgj1zqWKxxvVFAroz8NDh1GtcobyhatlrcXT9PhYOI,115598
16
15
  abstractassistant/ui/toast_manager.py,sha256=1aU4DPo-J45bC61gTEctHq98ZrHIFxRfZa_9Q8KF588,13721
17
16
  abstractassistant/ui/toast_window.py,sha256=BRSwEBlaND5LLipn1HOX0ISWxVH-zOHsYplFkiPaj_g,21727
18
17
  abstractassistant/ui/tts_state_manager.py,sha256=UF_zrfl9wf0hNHBGxevcoKxW5Dh7zXibUSVoSSjGP4o,10565
@@ -20,9 +19,9 @@ abstractassistant/ui/ui_styles.py,sha256=FvE2CVUbHmHu1PKVTBBGyhbt781qh4WjLMrHvil
20
19
  abstractassistant/utils/__init__.py,sha256=7Q3BxyXETkt3tm5trhuLTyL8PoECOK0QiK-0KUVAR2Q,16
21
20
  abstractassistant/utils/icon_generator.py,sha256=SWPgi1V6_8544Zbc2vAfFXAy15H35neyUGCYt2eKoic,16475
22
21
  abstractassistant/utils/markdown_renderer.py,sha256=u5tVIhulSwRYADiqJcZNoHhU8e6pJVgzrwZRd61Bov0,12585
23
- abstractassistant-0.3.2.dist-info/licenses/LICENSE,sha256=QUjFNAE-0yOkW9-Rle2axkpkt9H7xiZ2VbN-VeONhxc,1106
24
- abstractassistant-0.3.2.dist-info/METADATA,sha256=Z0vaLS5-e5Mm9urL8lLq7Rh-wvom7AtLdcCPdwSG-Uc,11320
25
- abstractassistant-0.3.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
26
- abstractassistant-0.3.2.dist-info/entry_points.txt,sha256=MIzeCh0XG6MbhIzBHtkdEjmjxYBsQrGFevq8Y1L8Jkc,118
27
- abstractassistant-0.3.2.dist-info/top_level.txt,sha256=oEcSXZAqbflTfZRfF4dogUq6TC1Nqyplq4JgC0CZnLI,34
28
- abstractassistant-0.3.2.dist-info/RECORD,,
22
+ abstractassistant-0.3.4.dist-info/licenses/LICENSE,sha256=QUjFNAE-0yOkW9-Rle2axkpkt9H7xiZ2VbN-VeONhxc,1106
23
+ abstractassistant-0.3.4.dist-info/METADATA,sha256=CXoP8mvao4NdI9qmyght-lTppQvuX3IgveQT7Ku0DVE,11564
24
+ abstractassistant-0.3.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
+ abstractassistant-0.3.4.dist-info/entry_points.txt,sha256=MIzeCh0XG6MbhIzBHtkdEjmjxYBsQrGFevq8Y1L8Jkc,118
26
+ abstractassistant-0.3.4.dist-info/top_level.txt,sha256=qZc_LQH3CBxLq2P4B1aHayzkj8hn0euR31edkXQVzDA,18
27
+ abstractassistant-0.3.4.dist-info/RECORD,,
@@ -1,2 +1 @@
1
1
  abstractassistant
2
- setup_macos_app