some changes
This commit is contained in:
@@ -30,6 +30,8 @@ class ChtWindow(Adw.ApplicationWindow):
|
||||
self._stream_mgr = None
|
||||
self._tracker = None
|
||||
self._known_frames = set()
|
||||
self._selected_frame = None # currently selected frame ID
|
||||
self._frame_widgets = {} # frame_id → outer Box widget
|
||||
|
||||
# Timeline is the central state machine
|
||||
self._timeline = Timeline()
|
||||
@@ -168,6 +170,8 @@ class ChtWindow(Adw.ApplicationWindow):
|
||||
self._stream_mgr.stop_all()
|
||||
self._stream_mgr = None
|
||||
self._known_frames = set()
|
||||
self._selected_frame = None
|
||||
self._frame_widgets = {}
|
||||
|
||||
self._connect_btn.set_label("Connect")
|
||||
self._connect_btn.remove_css_class("destructive-action")
|
||||
@@ -349,13 +353,28 @@ class ChtWindow(Adw.ApplicationWindow):
|
||||
outer.set_margin_top(4)
|
||||
outer.set_margin_bottom(4)
|
||||
|
||||
# Quick action buttons
|
||||
# Quick action buttons + model selector
|
||||
actions_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=4)
|
||||
for label in ACTIONS:
|
||||
for label, verb in ACTIONS.items():
|
||||
btn = Gtk.Button(label=label)
|
||||
btn.add_css_class("flat")
|
||||
btn.connect("clicked", lambda b, l=label: self._send_message(ACTIONS[l]))
|
||||
btn.connect("clicked", lambda b, v=verb: self._send_action(v))
|
||||
actions_box.append(btn)
|
||||
|
||||
# Model dropdown (right-aligned)
|
||||
spacer = Gtk.Box()
|
||||
spacer.set_hexpand(True)
|
||||
actions_box.append(spacer)
|
||||
|
||||
model_label = Gtk.Label(label="Model:")
|
||||
model_label.add_css_class("dim-label")
|
||||
actions_box.append(model_label)
|
||||
|
||||
self._model_dropdown = Gtk.DropDown.new_from_strings([])
|
||||
self._model_dropdown.set_size_request(200, -1)
|
||||
self._model_dropdown.connect("notify::selected", self._on_model_changed)
|
||||
actions_box.append(self._model_dropdown)
|
||||
|
||||
outer.append(actions_box)
|
||||
|
||||
# Text entry + send
|
||||
@@ -376,6 +395,27 @@ class ChtWindow(Adw.ApplicationWindow):
|
||||
frame.set_child(outer)
|
||||
return frame
|
||||
|
||||
def _send_action(self, verb: str):
|
||||
"""Send a predefined action with the selected frame."""
|
||||
if not self._selected_frame:
|
||||
self._append_agent_output("Select a frame first.\n")
|
||||
return
|
||||
self._send_message(f"{verb} @{self._selected_frame}")
|
||||
|
||||
def _select_frame(self, frame_id: str):
|
||||
"""Toggle selection of a frame thumbnail."""
|
||||
# Deselect previous
|
||||
if self._selected_frame and self._selected_frame in self._frame_widgets:
|
||||
self._frame_widgets[self._selected_frame].remove_css_class("frame-selected")
|
||||
|
||||
if self._selected_frame == frame_id:
|
||||
self._selected_frame = None
|
||||
return
|
||||
|
||||
self._selected_frame = frame_id
|
||||
if frame_id in self._frame_widgets:
|
||||
self._frame_widgets[frame_id].add_css_class("frame-selected")
|
||||
|
||||
def _send_message(self, text: str | None = None):
|
||||
if text is None:
|
||||
text = self._input_entry.get_text().strip()
|
||||
@@ -570,15 +610,37 @@ class ChtWindow(Adw.ApplicationWindow):
|
||||
buf.apply_tag(tag, buf.get_iter_at_mark(mark), it)
|
||||
buf.delete_mark(mark)
|
||||
|
||||
def _on_model_changed(self, dropdown, _pspec):
|
||||
idx = dropdown.get_selected()
|
||||
model = self._agent.available_models[idx] if idx < len(self._agent.available_models) else None
|
||||
if model:
|
||||
self._agent.model = model
|
||||
log.info("Model switched to %s", model)
|
||||
|
||||
def _populate_model_dropdown(self):
|
||||
models = self._agent.available_models
|
||||
if not models:
|
||||
return
|
||||
string_list = Gtk.StringList.new(models)
|
||||
self._model_dropdown.set_model(string_list)
|
||||
# Select current model
|
||||
current = self._agent.model
|
||||
for i, m in enumerate(models):
|
||||
if m == current:
|
||||
self._model_dropdown.set_selected(i)
|
||||
break
|
||||
|
||||
def _check_agent_auth(self):
|
||||
import os
|
||||
if os.environ.get("GROQ_API_KEY") or os.environ.get("OPENAI_API_KEY"):
|
||||
return # using external provider, no CLI check needed
|
||||
self._populate_model_dropdown()
|
||||
return
|
||||
err = check_claude_cli()
|
||||
if err:
|
||||
self._append_agent_output(f"⚠ {err}\n")
|
||||
else:
|
||||
self._append_agent_output(f"Agent ready ({self._agent.provider_name})\n")
|
||||
self._populate_model_dropdown()
|
||||
|
||||
def _append_agent_output(self, text: str):
|
||||
buf = self._agent_output_view.get_buffer()
|
||||
@@ -636,12 +698,11 @@ class ChtWindow(Adw.ApplicationWindow):
|
||||
label.set_ellipsize(Pango.EllipsizeMode.END)
|
||||
box.append(label)
|
||||
|
||||
# Click to highlight — does NOT switch mode or seek
|
||||
# (future: jump to timestamp in scrub bar without leaving live)
|
||||
gesture = Gtk.GestureClick()
|
||||
gesture.connect("released", lambda g, n, x, y, fid=frame_id: self._send_message(f"solve this @{fid}"))
|
||||
gesture.connect("released", lambda g, n, x, y, fid=frame_id: self._select_frame(fid))
|
||||
box.add_controller(gesture)
|
||||
|
||||
self._frame_widgets[frame_id] = box
|
||||
self._frames_strip.append(box)
|
||||
|
||||
# Auto-scroll to show the latest frame
|
||||
|
||||
Reference in New Issue
Block a user