abstractassistant 0.3.0__py3-none-any.whl → 0.3.2__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.
- abstractassistant/app.py +5 -0
- abstractassistant/ui/history_dialog.py +18 -0
- abstractassistant/ui/qt_bubble.py +106 -115
- abstractassistant/utils/icon_generator.py +6 -4
- {abstractassistant-0.3.0.dist-info → abstractassistant-0.3.2.dist-info}/METADATA +2 -2
- {abstractassistant-0.3.0.dist-info → abstractassistant-0.3.2.dist-info}/RECORD +10 -10
- {abstractassistant-0.3.0.dist-info → abstractassistant-0.3.2.dist-info}/WHEEL +0 -0
- {abstractassistant-0.3.0.dist-info → abstractassistant-0.3.2.dist-info}/entry_points.txt +0 -0
- {abstractassistant-0.3.0.dist-info → abstractassistant-0.3.2.dist-info}/licenses/LICENSE +0 -0
- {abstractassistant-0.3.0.dist-info → abstractassistant-0.3.2.dist-info}/top_level.txt +0 -0
abstractassistant/app.py
CHANGED
|
@@ -526,6 +526,11 @@ class AbstractAssistantApp:
|
|
|
526
526
|
voice_manager.stop()
|
|
527
527
|
if self.debug:
|
|
528
528
|
print("⏹ Voice stopped")
|
|
529
|
+
|
|
530
|
+
# Update icon status to ready since v0.5.1 callback won't fire for manual stops
|
|
531
|
+
self.update_icon_status("ready")
|
|
532
|
+
if self.debug:
|
|
533
|
+
print("🔄 Icon status set to ready after manual voice stop")
|
|
529
534
|
|
|
530
535
|
# Always show chat bubble on double click
|
|
531
536
|
if self.debug:
|
|
@@ -359,6 +359,24 @@ class iPhoneMessagesDialog:
|
|
|
359
359
|
layout.addStretch()
|
|
360
360
|
|
|
361
361
|
bubble_layout.addWidget(content_label)
|
|
362
|
+
|
|
363
|
+
# Add file attachment indicator if files were attached to this message
|
|
364
|
+
attached_files = msg.get('attached_files', [])
|
|
365
|
+
if attached_files:
|
|
366
|
+
file_indicator = QLabel(f"📎 {len(attached_files)} file{'s' if len(attached_files) > 1 else ''}")
|
|
367
|
+
file_indicator.setStyleSheet("""
|
|
368
|
+
QLabel {
|
|
369
|
+
background: transparent;
|
|
370
|
+
color: rgba(255, 255, 255, 0.7);
|
|
371
|
+
font-size: 11px;
|
|
372
|
+
font-weight: 500;
|
|
373
|
+
font-family: "Helvetica Neue", "Helvetica", Arial, sans-serif;
|
|
374
|
+
padding: 2px 0px;
|
|
375
|
+
margin: 0px;
|
|
376
|
+
}
|
|
377
|
+
""")
|
|
378
|
+
bubble_layout.addWidget(file_indicator)
|
|
379
|
+
|
|
362
380
|
main_layout.addWidget(container)
|
|
363
381
|
|
|
364
382
|
# Add timestamp below bubble (iPhone style)
|
|
@@ -289,6 +289,9 @@ class QtChatBubble(QWidget):
|
|
|
289
289
|
# Attached files for media handling (AbstractCore 2.4.5+)
|
|
290
290
|
self.attached_files: List[str] = []
|
|
291
291
|
|
|
292
|
+
# Track file attachments per message for history display
|
|
293
|
+
self.message_file_attachments: Dict[int, List[str]] = {}
|
|
294
|
+
|
|
292
295
|
# Initialize new manager classes
|
|
293
296
|
self.provider_manager = None
|
|
294
297
|
self.tts_state_manager = None
|
|
@@ -360,7 +363,10 @@ class QtChatBubble(QWidget):
|
|
|
360
363
|
)
|
|
361
364
|
|
|
362
365
|
# Set optimal size for modern chat interface - much wider to nearly touch screen edge
|
|
363
|
-
|
|
366
|
+
# Initial size - will be adjusted dynamically based on file attachments
|
|
367
|
+
self.base_width = 630
|
|
368
|
+
self.base_height = 196
|
|
369
|
+
self.setFixedSize(self.base_width, self.base_height)
|
|
364
370
|
self.position_near_tray()
|
|
365
371
|
|
|
366
372
|
# Main layout with minimal spacing
|
|
@@ -440,10 +446,7 @@ class QtChatBubble(QWidget):
|
|
|
440
446
|
self.full_voice_toggle.toggled.connect(self.on_full_voice_toggled)
|
|
441
447
|
header_layout.addWidget(self.full_voice_toggle)
|
|
442
448
|
|
|
443
|
-
#
|
|
444
|
-
self.voice_control_panel = self.create_voice_control_panel()
|
|
445
|
-
header_layout.addWidget(self.voice_control_panel)
|
|
446
|
-
self.voice_control_panel.hide() # Hidden initially
|
|
449
|
+
# Voice control panel removed - not needed
|
|
447
450
|
|
|
448
451
|
header_layout.addStretch()
|
|
449
452
|
|
|
@@ -565,8 +568,8 @@ class QtChatBubble(QWidget):
|
|
|
565
568
|
}
|
|
566
569
|
""")
|
|
567
570
|
self.attached_files_layout = QHBoxLayout(self.attached_files_container)
|
|
568
|
-
self.attached_files_layout.setContentsMargins(
|
|
569
|
-
self.attached_files_layout.setSpacing(
|
|
571
|
+
self.attached_files_layout.setContentsMargins(2, 2, 2, 2)
|
|
572
|
+
self.attached_files_layout.setSpacing(2)
|
|
570
573
|
self.attached_files_container.hide() # Initially hidden
|
|
571
574
|
input_layout.addWidget(self.attached_files_container)
|
|
572
575
|
layout.addWidget(self.input_container)
|
|
@@ -1140,6 +1143,7 @@ class QtChatBubble(QWidget):
|
|
|
1140
1143
|
|
|
1141
1144
|
if not self.attached_files:
|
|
1142
1145
|
self.attached_files_container.hide()
|
|
1146
|
+
self._adjust_window_size_for_attachments()
|
|
1143
1147
|
return
|
|
1144
1148
|
|
|
1145
1149
|
# Show container and add file chips
|
|
@@ -1155,14 +1159,14 @@ class QtChatBubble(QWidget):
|
|
|
1155
1159
|
QFrame {
|
|
1156
1160
|
background: rgba(0, 102, 204, 0.2);
|
|
1157
1161
|
border: 1px solid rgba(0, 102, 204, 0.4);
|
|
1158
|
-
border-radius:
|
|
1159
|
-
padding:
|
|
1162
|
+
border-radius: 6px;
|
|
1163
|
+
padding: 1px 4px;
|
|
1160
1164
|
}
|
|
1161
1165
|
""")
|
|
1162
1166
|
|
|
1163
1167
|
chip_layout = QHBoxLayout(file_chip)
|
|
1164
|
-
chip_layout.setContentsMargins(
|
|
1165
|
-
chip_layout.setSpacing(
|
|
1168
|
+
chip_layout.setContentsMargins(2, 1, 2, 1)
|
|
1169
|
+
chip_layout.setSpacing(2)
|
|
1166
1170
|
|
|
1167
1171
|
# File icon based on type
|
|
1168
1172
|
ext = os.path.splitext(file_name)[1].lower()
|
|
@@ -1182,18 +1186,18 @@ class QtChatBubble(QWidget):
|
|
|
1182
1186
|
icon = "📎"
|
|
1183
1187
|
|
|
1184
1188
|
file_label = QLabel(f"{icon} {file_name[:20]}{'...' if len(file_name) > 20 else ''}")
|
|
1185
|
-
file_label.setStyleSheet("background: transparent; border: none; color: rgba(255, 255, 255, 0.9); font-size:
|
|
1189
|
+
file_label.setStyleSheet("background: transparent; border: none; color: rgba(255, 255, 255, 0.9); font-size: 8px;")
|
|
1186
1190
|
chip_layout.addWidget(file_label)
|
|
1187
1191
|
|
|
1188
1192
|
# Remove button
|
|
1189
1193
|
remove_btn = QPushButton("✕")
|
|
1190
|
-
remove_btn.setFixedSize(
|
|
1194
|
+
remove_btn.setFixedSize(12, 12)
|
|
1191
1195
|
remove_btn.setStyleSheet("""
|
|
1192
1196
|
QPushButton {
|
|
1193
1197
|
background: transparent;
|
|
1194
1198
|
border: none;
|
|
1195
1199
|
color: rgba(255, 255, 255, 0.6);
|
|
1196
|
-
font-size:
|
|
1200
|
+
font-size: 8px;
|
|
1197
1201
|
padding: 0px;
|
|
1198
1202
|
}
|
|
1199
1203
|
QPushButton:hover {
|
|
@@ -1206,6 +1210,30 @@ class QtChatBubble(QWidget):
|
|
|
1206
1210
|
self.attached_files_layout.addWidget(file_chip)
|
|
1207
1211
|
|
|
1208
1212
|
self.attached_files_layout.addStretch()
|
|
1213
|
+
|
|
1214
|
+
# Adjust window size to accommodate file attachments
|
|
1215
|
+
self._adjust_window_size_for_attachments()
|
|
1216
|
+
|
|
1217
|
+
def _adjust_window_size_for_attachments(self):
|
|
1218
|
+
"""Dynamically adjust window size based on file attachments presence."""
|
|
1219
|
+
attachment_height = 28 # Height needed for file attachment container (reduced for compact chips)
|
|
1220
|
+
|
|
1221
|
+
if self.attached_files and self.attached_files_container.isVisible():
|
|
1222
|
+
# Files are attached - expand window
|
|
1223
|
+
new_height = self.base_height + attachment_height
|
|
1224
|
+
if self.debug:
|
|
1225
|
+
print(f"📏 Expanding window for attachments: {self.base_height} -> {new_height}")
|
|
1226
|
+
else:
|
|
1227
|
+
# No files attached - use base size
|
|
1228
|
+
new_height = self.base_height
|
|
1229
|
+
if self.debug:
|
|
1230
|
+
print(f"📏 Contracting window (no attachments): -> {new_height}")
|
|
1231
|
+
|
|
1232
|
+
# Apply new size
|
|
1233
|
+
self.setFixedSize(self.base_width, new_height)
|
|
1234
|
+
|
|
1235
|
+
# Reposition to maintain alignment with system tray
|
|
1236
|
+
self.position_near_tray()
|
|
1209
1237
|
|
|
1210
1238
|
def remove_attached_file(self, file_path):
|
|
1211
1239
|
"""Remove a file from the attached files list."""
|
|
@@ -1230,12 +1258,18 @@ class QtChatBubble(QWidget):
|
|
|
1230
1258
|
# 1. Clear input immediately
|
|
1231
1259
|
self.input_text.clear()
|
|
1232
1260
|
|
|
1233
|
-
# 2. Capture attached files
|
|
1261
|
+
# 2. Capture attached files for sending (but keep them attached)
|
|
1234
1262
|
media_files = self.attached_files.copy()
|
|
1263
|
+
|
|
1264
|
+
# 3. Store file attachments for this message in our tracking dict
|
|
1265
|
+
# We'll use the message count as a simple key
|
|
1266
|
+
if media_files:
|
|
1267
|
+
message_index = len(self.message_history) # Current message index before adding
|
|
1268
|
+
self.message_file_attachments[message_index] = media_files.copy()
|
|
1269
|
+
if self.debug:
|
|
1270
|
+
print(f"📎 Storing {len(media_files)} file(s) for message index {message_index}")
|
|
1235
1271
|
|
|
1236
|
-
#
|
|
1237
|
-
self.attached_files.clear()
|
|
1238
|
-
self.update_attached_files_display()
|
|
1272
|
+
# Note: We no longer clear attached_files here - they persist for reuse
|
|
1239
1273
|
|
|
1240
1274
|
# 4. Update UI for sending state
|
|
1241
1275
|
self.send_button.setEnabled(False)
|
|
@@ -1403,6 +1437,14 @@ class QtChatBubble(QWidget):
|
|
|
1403
1437
|
try:
|
|
1404
1438
|
self.voice_manager.stop()
|
|
1405
1439
|
self._update_tts_toggle_state()
|
|
1440
|
+
|
|
1441
|
+
# Manually trigger status update to "ready" since v0.5.1 callback won't fire
|
|
1442
|
+
# when we manually stop the audio
|
|
1443
|
+
if self.status_callback:
|
|
1444
|
+
if self.debug:
|
|
1445
|
+
print("🔊 QtChatBubble: TTS disabled, setting ready status")
|
|
1446
|
+
self.status_callback("ready")
|
|
1447
|
+
|
|
1406
1448
|
except Exception as e:
|
|
1407
1449
|
if self.debug:
|
|
1408
1450
|
if self.debug:
|
|
@@ -1507,6 +1549,13 @@ class QtChatBubble(QWidget):
|
|
|
1507
1549
|
# Safely update TTS toggle state
|
|
1508
1550
|
if hasattr(self, '_update_tts_toggle_state'):
|
|
1509
1551
|
self._update_tts_toggle_state()
|
|
1552
|
+
|
|
1553
|
+
# Manually trigger status update to "ready" since v0.5.1 callback won't fire
|
|
1554
|
+
# when we manually stop the audio
|
|
1555
|
+
if hasattr(self, 'status_callback') and self.status_callback:
|
|
1556
|
+
if self.debug:
|
|
1557
|
+
print("🔊 QtChatBubble: Manually stopped TTS, setting ready status")
|
|
1558
|
+
self.status_callback("ready")
|
|
1510
1559
|
|
|
1511
1560
|
except Exception as e:
|
|
1512
1561
|
if self.debug:
|
|
@@ -1680,7 +1729,10 @@ class QtChatBubble(QWidget):
|
|
|
1680
1729
|
self.input_container.hide()
|
|
1681
1730
|
|
|
1682
1731
|
# Update window size to be smaller but maintain wider width
|
|
1683
|
-
|
|
1732
|
+
voice_base_height = 120
|
|
1733
|
+
attachment_height = 28 if (self.attached_files and self.attached_files_container.isVisible()) else 0
|
|
1734
|
+
voice_height = voice_base_height + attachment_height
|
|
1735
|
+
self.setFixedSize(self.base_width, voice_height) # Dynamic height for voice mode
|
|
1684
1736
|
|
|
1685
1737
|
def show_text_ui(self):
|
|
1686
1738
|
"""Show the text input interface when exiting Full Voice Mode."""
|
|
@@ -1688,8 +1740,8 @@ class QtChatBubble(QWidget):
|
|
|
1688
1740
|
if hasattr(self, 'input_container'):
|
|
1689
1741
|
self.input_container.show()
|
|
1690
1742
|
|
|
1691
|
-
# Restore normal window size with wider width
|
|
1692
|
-
self.
|
|
1743
|
+
# Restore normal window size with wider width - use dynamic sizing
|
|
1744
|
+
self._adjust_window_size_for_attachments()
|
|
1693
1745
|
|
|
1694
1746
|
def update_status(self, status_text: str):
|
|
1695
1747
|
"""Update the status label with the given text."""
|
|
@@ -1727,13 +1779,7 @@ class QtChatBubble(QWidget):
|
|
|
1727
1779
|
current_state = self.voice_manager.get_state()
|
|
1728
1780
|
# No longer updating tts_toggle appearance - it's a simple user control
|
|
1729
1781
|
|
|
1730
|
-
#
|
|
1731
|
-
if hasattr(self, 'voice_control_panel'):
|
|
1732
|
-
if current_state in ['speaking', 'paused']:
|
|
1733
|
-
self.voice_control_panel.show()
|
|
1734
|
-
self._update_voice_control_panel(current_state)
|
|
1735
|
-
else:
|
|
1736
|
-
self.voice_control_panel.hide()
|
|
1782
|
+
# Voice control panel removed - no longer needed
|
|
1737
1783
|
|
|
1738
1784
|
if self.debug:
|
|
1739
1785
|
if self.debug:
|
|
@@ -1743,89 +1789,7 @@ class QtChatBubble(QWidget):
|
|
|
1743
1789
|
if self.debug:
|
|
1744
1790
|
print(f"❌ Error updating TTS toggle state: {e}")
|
|
1745
1791
|
|
|
1746
|
-
|
|
1747
|
-
"""Create a prominent voice control panel that appears when TTS is active."""
|
|
1748
|
-
panel = QWidget()
|
|
1749
|
-
layout = QHBoxLayout()
|
|
1750
|
-
layout.setContentsMargins(4, 2, 4, 2)
|
|
1751
|
-
layout.setSpacing(4)
|
|
1752
|
-
|
|
1753
|
-
# Pause/Resume button
|
|
1754
|
-
self.voice_pause_button = QPushButton("⏸")
|
|
1755
|
-
self.voice_pause_button.setFixedSize(24, 24)
|
|
1756
|
-
self.voice_pause_button.setToolTip("Pause/Resume TTS (Space)")
|
|
1757
|
-
self.voice_pause_button.clicked.connect(self.on_tts_single_click)
|
|
1758
|
-
self.voice_pause_button.setStyleSheet("""
|
|
1759
|
-
QPushButton {
|
|
1760
|
-
background: rgba(255, 255, 255, 0.1);
|
|
1761
|
-
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
1762
|
-
border-radius: 12px;
|
|
1763
|
-
font-size: 12px;
|
|
1764
|
-
color: rgba(255, 255, 255, 0.9);
|
|
1765
|
-
font-weight: bold;
|
|
1766
|
-
}
|
|
1767
|
-
QPushButton:hover {
|
|
1768
|
-
background: rgba(255, 255, 255, 0.2);
|
|
1769
|
-
border: 1px solid rgba(255, 255, 255, 0.3);
|
|
1770
|
-
}
|
|
1771
|
-
QPushButton:pressed {
|
|
1772
|
-
background: rgba(255, 255, 255, 0.05);
|
|
1773
|
-
}
|
|
1774
|
-
""")
|
|
1775
|
-
layout.addWidget(self.voice_pause_button)
|
|
1776
|
-
|
|
1777
|
-
# Stop button
|
|
1778
|
-
self.voice_stop_button = QPushButton("⏹")
|
|
1779
|
-
self.voice_stop_button.setFixedSize(24, 24)
|
|
1780
|
-
self.voice_stop_button.setToolTip("Stop TTS (Escape)")
|
|
1781
|
-
self.voice_stop_button.clicked.connect(self.on_tts_double_click)
|
|
1782
|
-
self.voice_stop_button.setStyleSheet("""
|
|
1783
|
-
QPushButton {
|
|
1784
|
-
background: rgba(255, 100, 100, 0.1);
|
|
1785
|
-
border: 1px solid rgba(255, 100, 100, 0.3);
|
|
1786
|
-
border-radius: 12px;
|
|
1787
|
-
font-size: 12px;
|
|
1788
|
-
color: rgba(255, 200, 200, 0.9);
|
|
1789
|
-
font-weight: bold;
|
|
1790
|
-
}
|
|
1791
|
-
QPushButton:hover {
|
|
1792
|
-
background: rgba(255, 100, 100, 0.2);
|
|
1793
|
-
border: 1px solid rgba(255, 100, 100, 0.4);
|
|
1794
|
-
}
|
|
1795
|
-
QPushButton:pressed {
|
|
1796
|
-
background: rgba(255, 100, 100, 0.05);
|
|
1797
|
-
}
|
|
1798
|
-
""")
|
|
1799
|
-
layout.addWidget(self.voice_stop_button)
|
|
1800
|
-
|
|
1801
|
-
# Status text
|
|
1802
|
-
self.voice_status_label = QLabel("Speaking...")
|
|
1803
|
-
self.voice_status_label.setStyleSheet("""
|
|
1804
|
-
QLabel {
|
|
1805
|
-
color: rgba(255, 255, 255, 0.8);
|
|
1806
|
-
font-size: 10px;
|
|
1807
|
-
font-weight: 500;
|
|
1808
|
-
padding: 2px 4px;
|
|
1809
|
-
}
|
|
1810
|
-
""")
|
|
1811
|
-
layout.addWidget(self.voice_status_label)
|
|
1812
|
-
|
|
1813
|
-
panel.setLayout(layout)
|
|
1814
|
-
return panel
|
|
1815
|
-
|
|
1816
|
-
def _update_voice_control_panel(self, state):
|
|
1817
|
-
"""Update the voice control panel based on TTS state."""
|
|
1818
|
-
if not hasattr(self, 'voice_control_panel'):
|
|
1819
|
-
return
|
|
1820
|
-
|
|
1821
|
-
if state == 'speaking':
|
|
1822
|
-
self.voice_pause_button.setText("⏸")
|
|
1823
|
-
self.voice_pause_button.setToolTip("Pause TTS (Space)")
|
|
1824
|
-
self.voice_status_label.setText("Speaking...")
|
|
1825
|
-
elif state == 'paused':
|
|
1826
|
-
self.voice_pause_button.setText("▶")
|
|
1827
|
-
self.voice_pause_button.setToolTip("Resume TTS (Space)")
|
|
1828
|
-
self.voice_status_label.setText("Paused")
|
|
1792
|
+
# Voice control panel methods removed - not needed
|
|
1829
1793
|
|
|
1830
1794
|
def setup_keyboard_shortcuts(self):
|
|
1831
1795
|
"""Setup keyboard shortcuts for voice control."""
|
|
@@ -1975,7 +1939,7 @@ class QtChatBubble(QWidget):
|
|
|
1975
1939
|
reply = QMessageBox.question(
|
|
1976
1940
|
self,
|
|
1977
1941
|
"Clear Session",
|
|
1978
|
-
"Are you sure you want to clear the current session?\nThis will remove all messages and reset the token count.",
|
|
1942
|
+
"Are you sure you want to clear the current session?\nThis will remove all messages, attached files, and reset the token count.",
|
|
1979
1943
|
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
|
|
1980
1944
|
QMessageBox.StandardButton.No
|
|
1981
1945
|
)
|
|
@@ -1996,9 +1960,14 @@ class QtChatBubble(QWidget):
|
|
|
1996
1960
|
self.token_count = 0
|
|
1997
1961
|
self.update_token_display()
|
|
1998
1962
|
|
|
1963
|
+
# Clear attached files as part of session clearing
|
|
1964
|
+
self.attached_files.clear()
|
|
1965
|
+
self.message_file_attachments.clear()
|
|
1966
|
+
self.update_attached_files_display()
|
|
1967
|
+
|
|
1999
1968
|
if self.debug:
|
|
2000
1969
|
if self.debug:
|
|
2001
|
-
print("🧹 Session cleared")
|
|
1970
|
+
print("🧹 Session cleared (including attached files and file tracking)")
|
|
2002
1971
|
|
|
2003
1972
|
def load_session(self):
|
|
2004
1973
|
"""Load a session using AbstractCore via LLMManager."""
|
|
@@ -2131,7 +2100,7 @@ class QtChatBubble(QWidget):
|
|
|
2131
2100
|
|
|
2132
2101
|
# Convert AbstractCore messages to our format
|
|
2133
2102
|
self.message_history = []
|
|
2134
|
-
for msg in session_messages:
|
|
2103
|
+
for i, msg in enumerate(session_messages):
|
|
2135
2104
|
# Skip system messages
|
|
2136
2105
|
if hasattr(msg, 'role') and msg.role == 'system':
|
|
2137
2106
|
continue
|
|
@@ -2141,7 +2110,8 @@ class QtChatBubble(QWidget):
|
|
|
2141
2110
|
'type': getattr(msg, 'role', 'unknown'),
|
|
2142
2111
|
'content': getattr(msg, 'content', str(msg)),
|
|
2143
2112
|
'provider': self.current_provider,
|
|
2144
|
-
'model': self.current_model
|
|
2113
|
+
'model': self.current_model,
|
|
2114
|
+
'attached_files': self.message_file_attachments.get(len(self.message_history), [])
|
|
2145
2115
|
}
|
|
2146
2116
|
self.message_history.append(message)
|
|
2147
2117
|
|
|
@@ -2154,6 +2124,27 @@ class QtChatBubble(QWidget):
|
|
|
2154
2124
|
if self.debug:
|
|
2155
2125
|
print(f"❌ Error updating message history from session: {e}")
|
|
2156
2126
|
|
|
2127
|
+
def _rebuild_chat_display(self):
|
|
2128
|
+
"""Rebuild chat display after session loading.
|
|
2129
|
+
|
|
2130
|
+
Since the main bubble doesn't have a chat display area, this method
|
|
2131
|
+
updates the history dialog if it's currently open.
|
|
2132
|
+
"""
|
|
2133
|
+
try:
|
|
2134
|
+
# If history dialog is open, refresh it with new message history
|
|
2135
|
+
if self.history_dialog and self.history_dialog.isVisible():
|
|
2136
|
+
self.history_dialog.refresh_messages(self.message_history)
|
|
2137
|
+
if self.debug:
|
|
2138
|
+
print("🔄 Refreshed history dialog with loaded session messages")
|
|
2139
|
+
|
|
2140
|
+
# No action needed if history dialog is closed since main bubble has no chat display
|
|
2141
|
+
if self.debug:
|
|
2142
|
+
print("✅ Chat display rebuild completed")
|
|
2143
|
+
|
|
2144
|
+
except Exception as e:
|
|
2145
|
+
if self.debug:
|
|
2146
|
+
print(f"❌ Error rebuilding chat display: {e}")
|
|
2147
|
+
|
|
2157
2148
|
def _update_token_count_from_session(self):
|
|
2158
2149
|
"""Update token count from AbstractCore session."""
|
|
2159
2150
|
try:
|
|
@@ -324,9 +324,10 @@ class IconGenerator:
|
|
|
324
324
|
bar_color = (r, g, b, 255)
|
|
325
325
|
|
|
326
326
|
# Draw 5 vertical bars with different vibration frequencies (like voice visualizer)
|
|
327
|
+
# Made much larger to match other menu bar icons
|
|
327
328
|
bar_count = 5
|
|
328
|
-
bar_width = size * 0.08
|
|
329
|
-
bar_spacing = size * 0.12
|
|
329
|
+
bar_width = size * 0.15 # Increased from 0.08 to 0.15 (almost 2x wider)
|
|
330
|
+
bar_spacing = size * 0.18 # Increased from 0.12 to 0.18 (more spacing)
|
|
330
331
|
|
|
331
332
|
for i in range(bar_count):
|
|
332
333
|
# Each bar has slightly different frequency for realistic voice effect
|
|
@@ -334,8 +335,9 @@ class IconGenerator:
|
|
|
334
335
|
bar_vibration = math.sin(current_time * bar_freq * 2 * math.pi)
|
|
335
336
|
|
|
336
337
|
# Bar height varies with vibration (like audio visualizer)
|
|
337
|
-
|
|
338
|
-
|
|
338
|
+
# Made much taller to be more visible
|
|
339
|
+
base_height = size * 0.25 # Increased from 0.15 to 0.25
|
|
340
|
+
vibration_height = size * 0.35 * abs(bar_vibration) # Increased from 0.25 to 0.35
|
|
339
341
|
total_height = base_height + vibration_height
|
|
340
342
|
|
|
341
343
|
# Position bars horizontally across the icon
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: abstractassistant
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
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
|
|
@@ -28,7 +28,7 @@ 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.
|
|
31
|
+
Requires-Dist: abstractvoice>=0.5.1
|
|
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"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
setup_macos_app.py,sha256=9dIPr9TipjtgdIhd0MnR2syRNoFyBVMnRsWDW0UCT3A,10736
|
|
2
2
|
abstractassistant/__init__.py,sha256=homfqMDh6sX2nBROtk6-y72jnrStPph8gEOeT0OjKyU,35
|
|
3
|
-
abstractassistant/app.py,sha256=
|
|
3
|
+
abstractassistant/app.py,sha256=yGFszbaqja_Y1ejSMcVYIcq8f1qdeZpVTb032geI-ZE,40374
|
|
4
4
|
abstractassistant/cli.py,sha256=SQPxQCLjX-LOlhSEvG302D0AOyxlxo5QM2imxr9wxmc,4385
|
|
5
5
|
abstractassistant/config.py,sha256=KodfPYTpHtavJyne-h-B-r3kbEt1uusSY8GknGLtDL8,5809
|
|
6
6
|
abstractassistant/create_app_bundle.py,sha256=LAZdp2C90ikMVd3KPdwNYBYUASbHpypOJIwvx6fQyXM,1698
|
|
@@ -10,19 +10,19 @@ abstractassistant/core/llm_manager.py,sha256=hJun-nDfRv9zxv_3tfrHAmVYSYT96E-0zDJ
|
|
|
10
10
|
abstractassistant/core/tts_manager.py,sha256=Cxh302EgIycwkWxe7XntmLW-j_WusbJOYRCs3Jms3CU,9892
|
|
11
11
|
abstractassistant/ui/__init__.py,sha256=aRNE2pS50nFAX6y--rSGMNYwhz905g14gRd6g4BolYU,13
|
|
12
12
|
abstractassistant/ui/chat_bubble.py,sha256=TE6zPtQ46I9grKGAb744wHqk4yO6-und3iif8_33XGk,11357
|
|
13
|
-
abstractassistant/ui/history_dialog.py,sha256=
|
|
13
|
+
abstractassistant/ui/history_dialog.py,sha256=949l8fVgRpUfRGcoOVRutERVXrShYgpKkFJCxo2JG-4,19323
|
|
14
14
|
abstractassistant/ui/provider_manager.py,sha256=9IM-BxIs6lUlk6cDCBi7oZFMXmn4CFMlxh0s-_vhzXY,8403
|
|
15
|
-
abstractassistant/ui/qt_bubble.py,sha256=
|
|
15
|
+
abstractassistant/ui/qt_bubble.py,sha256=cBjViRyusWWEmX5bHz4k-W8mUFRY6RPOuUq5AyN7ciI,97030
|
|
16
16
|
abstractassistant/ui/toast_manager.py,sha256=1aU4DPo-J45bC61gTEctHq98ZrHIFxRfZa_9Q8KF588,13721
|
|
17
17
|
abstractassistant/ui/toast_window.py,sha256=BRSwEBlaND5LLipn1HOX0ISWxVH-zOHsYplFkiPaj_g,21727
|
|
18
18
|
abstractassistant/ui/tts_state_manager.py,sha256=UF_zrfl9wf0hNHBGxevcoKxW5Dh7zXibUSVoSSjGP4o,10565
|
|
19
19
|
abstractassistant/ui/ui_styles.py,sha256=FvE2CVUbHmHu1PKVTBBGyhbt781qh4WjLMrHviln39s,13120
|
|
20
20
|
abstractassistant/utils/__init__.py,sha256=7Q3BxyXETkt3tm5trhuLTyL8PoECOK0QiK-0KUVAR2Q,16
|
|
21
|
-
abstractassistant/utils/icon_generator.py,sha256=
|
|
21
|
+
abstractassistant/utils/icon_generator.py,sha256=SWPgi1V6_8544Zbc2vAfFXAy15H35neyUGCYt2eKoic,16475
|
|
22
22
|
abstractassistant/utils/markdown_renderer.py,sha256=u5tVIhulSwRYADiqJcZNoHhU8e6pJVgzrwZRd61Bov0,12585
|
|
23
|
-
abstractassistant-0.3.
|
|
24
|
-
abstractassistant-0.3.
|
|
25
|
-
abstractassistant-0.3.
|
|
26
|
-
abstractassistant-0.3.
|
|
27
|
-
abstractassistant-0.3.
|
|
28
|
-
abstractassistant-0.3.
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|