chore: checkpoint current performance and UI changes
This commit is contained in:
@@ -115,10 +115,23 @@ class ChatAgentsMixin:
|
||||
if err:
|
||||
self.status_message.emit(tr("chatpanel.agent_list_error", err=err))
|
||||
|
||||
w = AgentWorker(job)
|
||||
w.finished_ok.connect(done)
|
||||
self._agent_worker = w
|
||||
w.start()
|
||||
# Model discovery can involve a provider/network request. Constructing
|
||||
# the chat panel during startup must not wait for it; schedule it after
|
||||
# the first event-loop turn so the initial shell can paint immediately.
|
||||
from PySide6.QtCore import QTimer
|
||||
|
||||
if getattr(self, "_agent_refresh_pending", False):
|
||||
return
|
||||
self._agent_refresh_pending = True
|
||||
|
||||
def start_worker() -> None:
|
||||
self._agent_refresh_pending = False
|
||||
w = AgentWorker(job)
|
||||
w.finished_ok.connect(done)
|
||||
self._agent_worker = w
|
||||
w.start()
|
||||
|
||||
QTimer.singleShot(0, start_worker)
|
||||
|
||||
def _populate_agents(self, models, keep: str) -> None:
|
||||
"""Đổ danh sách vào bộ chọn Agent.
|
||||
|
||||
@@ -51,6 +51,8 @@ class MessageBubble(QFrame):
|
||||
super().__init__()
|
||||
self.role = role
|
||||
self._text = ""
|
||||
self._stream_pending = False
|
||||
self._render_count = 0
|
||||
self._collapsible = collapsible
|
||||
self._title = title
|
||||
self._head = None
|
||||
@@ -164,12 +166,20 @@ class MessageBubble(QFrame):
|
||||
def append_delta(self, delta: str) -> None:
|
||||
"""Nối thêm một mẩu văn bản đang phát dần từ model rồi vẽ lại dạng markdown."""
|
||||
self._text += delta
|
||||
self.set_markdown(self._text)
|
||||
if not self._stream_pending:
|
||||
self._stream_pending = True
|
||||
QTimer.singleShot(40, self.flush_stream)
|
||||
|
||||
def flush_stream(self) -> None:
|
||||
if self._stream_pending:
|
||||
self._stream_pending = False
|
||||
self.set_markdown(self._text)
|
||||
|
||||
def set_markdown(self, text: str) -> None:
|
||||
"""Đặt toàn bộ nội dung, hiển thị dạng markdown, rồi co giãn lại chiều cao."""
|
||||
self._text = text
|
||||
self.body.setMarkdown(text)
|
||||
self._render_count += 1
|
||||
self._autosize()
|
||||
if self._collapsible:
|
||||
self._update_head()
|
||||
@@ -393,4 +403,3 @@ class ChatView(QScrollArea):
|
||||
ChatHistoryWidget = ChatView
|
||||
|
||||
__all__ = ["ChatView", "ChatHistoryWidget", "MessageBubble"]
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ from PySide6.QtWidgets import QHBoxLayout, QLabel, QTabWidget, QVBoxLayout, QWid
|
||||
from ...core import audit_log
|
||||
from ...i18n import on_language_changed, tr
|
||||
from ...state import AppContext
|
||||
from ...performance import span
|
||||
from .tabs.action_logs_tab import ActionLogsTab
|
||||
from .tabs.agent_status_tab import AgentStatusTab
|
||||
from .tabs.mcp_tab import McpTab
|
||||
@@ -282,12 +283,13 @@ class MonitoringTab(QWidget):
|
||||
"""
|
||||
start = date.today() - timedelta(days=_LOG_WINDOW_DAYS)
|
||||
shared_dir = self.ctx.config.shared_dir
|
||||
if shared_dir:
|
||||
from ...core import telemetry_shared
|
||||
shared_events = telemetry_shared.load_shared_audit_events(shared_dir, start=start)
|
||||
if shared_events:
|
||||
return shared_events
|
||||
return audit_log.load_events(start=start)
|
||||
with span("monitoring.load_events", window_days=_LOG_WINDOW_DAYS):
|
||||
if shared_dir:
|
||||
from ...core import telemetry_shared
|
||||
shared_events = telemetry_shared.load_shared_audit_events(shared_dir, start=start)
|
||||
if shared_events:
|
||||
return shared_events
|
||||
return audit_log.load_events(start=start)
|
||||
|
||||
def _apply_events_to_event_tabs(self, events: List[dict]) -> None:
|
||||
"""Filters the ALREADY-LOADED event list (see ``_load_events`` — one
|
||||
|
||||
@@ -32,9 +32,7 @@ from .rail_metrics import _NAV_MIN_WIDTH
|
||||
from .tray_manager import TrayManager
|
||||
from ...state import AppContext
|
||||
from ...core.task_scheduler import TaskScheduler
|
||||
from ...ui.cowork_tab import CoworkTab
|
||||
from ...ui.sidebar import HistorySidebar
|
||||
from ..graph.structure_graph_view import StructureGraphView
|
||||
from ...ui.workspace_tab import WorkspaceTab
|
||||
|
||||
|
||||
@@ -111,10 +109,9 @@ class MainWindow(NavRailMixin, RailProjectMixin, TopBarMixin,
|
||||
# Workspace screen (per selected project). GraphRAG's heavy
|
||||
# QtWebEngine is still built lazily on first display
|
||||
# (StructureGraphView._ensure_web).
|
||||
from ...ui.cowork_tab import CoworkTab
|
||||
self.cowork = CoworkTab(ctx)
|
||||
self.structure = StructureGraphView(ctx)
|
||||
self.structure.status_message.connect(self.statusBar().showMessage)
|
||||
self.cowork.output_changed.connect(self.structure.schedule_rescan)
|
||||
self.structure = None
|
||||
self.cowork.status_message.connect(self.statusBar().showMessage)
|
||||
# Refresh History (list + running markers + current highlight) whenever a
|
||||
# conversation is created/updated or a turn finishes.
|
||||
|
||||
@@ -42,7 +42,14 @@ class SessionEventsMixin:
|
||||
self.sidebar.refresh()
|
||||
self._refresh_rail_recents() # the rail shortcut follows the panel
|
||||
|
||||
QTimer.singleShot(0, _do)
|
||||
# Coalesce bursts from turn/tool/history signals into one sidebar read.
|
||||
timer = getattr(self, "_history_refresh_timer", None)
|
||||
if timer is None:
|
||||
timer = QTimer(self)
|
||||
timer.setSingleShot(True)
|
||||
timer.timeout.connect(_do)
|
||||
self._history_refresh_timer = timer
|
||||
timer.start(0)
|
||||
def _on_scheduled_task_done(self, task_id: str, ok: bool) -> None:
|
||||
"""Desktop notification for a finished scheduled task (toast always,
|
||||
tray balloon when the window isn't focused), then refresh History —
|
||||
@@ -106,4 +113,5 @@ class SessionEventsMixin:
|
||||
"""Project được tạo/sửa/xoá: gom nhóm lại cột lịch sử và cập nhật nhãn thư mục."""
|
||||
self.sidebar.refresh() # History regroups by project
|
||||
self.cowork._apply_output_folder_label() # project may have been renamed
|
||||
self.structure._refresh_project_combo() # GraphRAG's project lock list follows too
|
||||
if getattr(self, "structure", None) is not None:
|
||||
self.structure._refresh_project_combo() # GraphRAG's project lock list follows too
|
||||
|
||||
Reference in New Issue
Block a user