Feature/fsg gamma team ui fix #3
@@ -87,6 +87,28 @@ def main() -> int:
|
||||
fails.append(f"thieu nut {name} tren thanh cong cu")
|
||||
print(f"nut tren thanh cong cu: {c.skills_btn.text()!r}, {c._new_btn.text()!r}")
|
||||
|
||||
# the status strip, read left to right, is
|
||||
# Agent: … · Định tuyến: … · ↓in ↑out · $cost · 📁 folder
|
||||
from PySide6.QtCore import QPoint as _P
|
||||
|
||||
bar = c._usage_total_lbl.parentWidget()
|
||||
def _x(widget):
|
||||
return widget.mapTo(bar, _P(0, 0)).x()
|
||||
|
||||
usage_text = c._usage_total_lbl.text()
|
||||
print(f"usage tren dai: {usage_text!r}")
|
||||
if not usage_text.strip():
|
||||
fails.append("dai duoi khong hien token/chi phi cua thread da mo")
|
||||
order = [("Agent", _x(c._agent_lbl)), ("Dinh tuyen", _x(c.routing_toggle)),
|
||||
("usage", _x(c._usage_total_lbl))]
|
||||
folder = getattr(c, "folder_lbl", None)
|
||||
if folder is not None:
|
||||
order.append(("thu muc", _x(folder)))
|
||||
print("thu tu: " + " < ".join(f"{n}({x})" for n, x in order))
|
||||
for (n1, x1), (n2, x2) in zip(order, order[1:]):
|
||||
if x1 >= x2:
|
||||
fails.append(f"dai duoi sai thu tu: {n1} khong dung truoc {n2}")
|
||||
|
||||
# the drawing gives Cowork two columns; History lives in the rail's RECENTS
|
||||
# and its pane arrives folded to the strip the drawing keeps
|
||||
w = win.workspace
|
||||
|
||||
+37
-5
@@ -143,7 +143,7 @@ class ChatPanel(QWidget):
|
||||
self._usage_total_lbl = QLabel("")
|
||||
self._usage_total_lbl.setObjectName("hint")
|
||||
self._usage_total_lbl.setStyleSheet(f"color: {current_palette().text_faint};")
|
||||
self.composer.add_bottom_left(self._usage_total_lbl)
|
||||
|
||||
|
||||
# Per-tab "Agent" = which MODEL this tab uses (e.g. deepseek / gemma /
|
||||
# qwen for the local provider). Cowork and Code pick independently and
|
||||
@@ -167,13 +167,19 @@ class ChatPanel(QWidget):
|
||||
self.agent_combo.setMinimumWidth(150)
|
||||
self.agent_combo.setToolTip(tr("chatpanel.agent_tooltip"))
|
||||
self.agent_combo.currentIndexChanged.connect(self._on_agent_changed)
|
||||
self.composer.add_bottom_right(self._agent_lbl)
|
||||
self.composer.add_bottom_right(self.agent_combo)
|
||||
self.composer.add_bottom_left(self._agent_lbl)
|
||||
self.composer.add_bottom_left(self.agent_combo)
|
||||
# Off/Auto/Manual routing toggle — lets the router pick the best-fit
|
||||
# model per message (see core/routing + _apply_routing).
|
||||
from .routing_toggle import RoutingToggle
|
||||
self.routing_toggle = RoutingToggle(ctx, self.kind)
|
||||
self.composer.add_bottom_right(self.routing_toggle)
|
||||
# The drawing reads the strip left to right as
|
||||
# Agent: … · Định tuyến: … · ↓in ↑out · $cost · 📁 folder
|
||||
# so these sit together on the left, with the folder box the Cowork tab
|
||||
# appends landing after them. Nén and Tự chạy stay on the right, where
|
||||
# the control inventory marks them "giữ nguyên tại chỗ".
|
||||
self.composer.add_bottom_left(self.routing_toggle)
|
||||
self.composer.add_bottom_left(self._usage_total_lbl)
|
||||
# Manual "compress conversation" — trim old history to cut tokens.
|
||||
self.compress_btn = QPushButton(tr("chatpanel.compress_btn"))
|
||||
self.compress_btn.setIcon(app_icon("compress"))
|
||||
@@ -1413,6 +1419,26 @@ class ChatPanel(QWidget):
|
||||
return [e for e in ut.load_events()
|
||||
if e.get("source") == self.kind and e.get("label") == label]
|
||||
|
||||
def refresh_usage(self) -> None:
|
||||
"""Show what this conversation has already cost.
|
||||
|
||||
The label was written only at the end of a turn, so opening a thread
|
||||
from History left the strip blank however much it had spent.
|
||||
"""
|
||||
from ..core import model_pricing as mp
|
||||
from ..core import usage_tracker as ut
|
||||
|
||||
cur = self._usage_snapshot()
|
||||
if not (cur["in"] or cur["out"] or cur["cache"]):
|
||||
self._usage_total_lbl.setText("")
|
||||
return
|
||||
# same source _show_usage reads, so the two never disagree
|
||||
pricing = {**ut.DEFAULT_PRICING, **(self.ctx.config.data.get("usage") or {})}
|
||||
self._usage_total_lbl.setText(
|
||||
f"↓{mp.format_tokens(cur['in'])} ↑{mp.format_tokens(cur['out'])} "
|
||||
f"▤{mp.format_tokens(cur['in'] + cur['out'] + cur['cache'])} "
|
||||
f"{ut.format_cost(self._session_cost_usd(), pricing)}")
|
||||
|
||||
def _usage_snapshot(self) -> Dict[str, int]:
|
||||
"""Cumulative in/out/cache tokens for THIS conversation so far."""
|
||||
snap = {"in": 0, "out": 0, "cache": 0}
|
||||
@@ -1684,10 +1710,16 @@ class ChatPanel(QWidget):
|
||||
self.history_changed.emit() # current view changed → refresh History highlight
|
||||
|
||||
def _notify_title(self) -> None:
|
||||
"""Let a screen that heads itself with the thread title follow along."""
|
||||
"""Let a screen that heads itself with the thread title follow along.
|
||||
|
||||
The thread also decides what the usage strip should read, so refresh
|
||||
that here rather than at each of the three places the title changes.
|
||||
"""
|
||||
hook = getattr(self, "refresh_title", None)
|
||||
if callable(hook):
|
||||
hook()
|
||||
if getattr(self, "_usage_total_lbl", None) is not None:
|
||||
self.refresh_usage()
|
||||
|
||||
def load_conversation(self, conv: Dict[str, Any]) -> None:
|
||||
"""Switch the view to a stored conversation. Allowed while work is running —
|
||||
|
||||
Reference in New Issue
Block a user