This commit is contained in:
2026-02-21 18:36:37 -05:00
parent 383a3f3971
commit 7427b7a9d7
5 changed files with 154 additions and 37 deletions

143
gui.py
View File

@@ -426,15 +426,8 @@ class App:
dpg.delete_item("tool_log_scroll", children_only=True)
for i, (script, result) in enumerate(self._tool_log, 1):
with dpg.group(parent="tool_log_scroll"):
dpg.add_text(f"Call #{i}", color=(140, 200, 255))
dpg.add_input_text(
default_value=script,
multiline=True,
readonly=True,
width=-1,
height=72,
)
dpg.add_text("Result:", color=(180, 255, 180))
first_line = script.strip().splitlines()[0][:80] if script.strip() else "(empty)"
dpg.add_text(f"Call #{i}: {first_line}", color=(140, 200, 255))
dpg.add_input_text(
default_value=result,
multiline=True,
@@ -455,8 +448,12 @@ class App:
self.config["screenshots"]["base_dir"] = dpg.get_value("shots_base_dir")
self.config["files"]["paths"] = self.files
self.config["screenshots"]["paths"] = self.screenshots
raw = dpg.get_value("discussion_box")
self.history = [s.strip() for s in raw.split("---") if s.strip()]
# Pull latest content edits from disc widgets
for i, entry in enumerate(self.disc_entries):
tag = f"disc_content_{i}"
if dpg.does_item_exist(tag):
entry["content"] = dpg.get_value(tag)
self.history = self._disc_serialize()
self.config["discussion"] = {"history": self.history}
self.config["ai"] = {
"provider": self.current_provider,
@@ -672,6 +669,7 @@ class App:
self.available_models = []
self._rebuild_models_list()
self._fetch_models(self.current_provider)
self._rebuild_disc_list()
def cb_model_changed(self, sender, app_data):
if app_data:
@@ -697,6 +695,103 @@ class App:
# ---------------------------------------------------------------- build ui
# ------------------------------------------------------------ disc history
def _disc_serialize(self) -> list[str]:
"""Flatten disc_entries back to a single TOML history string per logical block."""
lines = []
for e in self.disc_entries:
lines.append(f"{e['role']}:\n{e['content']}")
return lines
def _rebuild_disc_list(self):
if not dpg.does_item_exist("disc_scroll"):
return
dpg.delete_item("disc_scroll", children_only=True)
for i, entry in enumerate(self.disc_entries):
with dpg.group(parent="disc_scroll"):
with dpg.group(horizontal=True):
dpg.add_combo(
tag=f"disc_role_{i}",
items=DISC_ROLES,
default_value=entry["role"],
width=120,
callback=self._make_disc_role_cb(i),
)
dpg.add_button(
label="Insert Before",
callback=self._make_disc_insert_cb(i),
)
dpg.add_button(
label="Remove",
callback=self._make_disc_remove_cb(i),
)
dpg.add_input_text(
tag=f"disc_content_{i}",
default_value=entry["content"],
multiline=True,
width=-1,
height=100,
callback=self._make_disc_content_cb(i),
on_enter=False,
)
dpg.add_separator()
def _make_disc_role_cb(self, idx: int):
def cb(sender, app_data):
if idx < len(self.disc_entries):
self.disc_entries[idx]["role"] = app_data
return cb
def _make_disc_content_cb(self, idx: int):
def cb(sender, app_data):
if idx < len(self.disc_entries):
self.disc_entries[idx]["content"] = app_data
return cb
def _make_disc_insert_cb(self, idx: int):
def cb():
self.disc_entries.insert(idx, {"role": "User", "content": ""})
self._rebuild_disc_list()
return cb
def _make_disc_remove_cb(self, idx: int):
def cb():
if idx < len(self.disc_entries):
self.disc_entries.pop(idx)
self._rebuild_disc_list()
return cb
def cb_disc_append_entry(self):
self.disc_entries.append({"role": "User", "content": ""})
self._rebuild_disc_list()
def cb_disc_clear(self):
self.disc_entries.clear()
self._rebuild_disc_list()
def cb_disc_save(self):
# Pull any in-progress edits from widgets into disc_entries
for i, entry in enumerate(self.disc_entries):
tag = f"disc_content_{i}"
if dpg.does_item_exist(tag):
entry["content"] = dpg.get_value(tag)
self._flush_to_config()
save_config(self.config)
self._update_status("discussion saved")
def cb_append_message_to_history(self):
msg = dpg.get_value("ai_input")
if msg:
self.disc_entries.append({"role": "User", "content": msg})
self._rebuild_disc_list()
def cb_append_response_to_history(self):
resp = self.ai_response
if resp:
self.disc_entries.append({"role": "AI", "content": resp})
self._rebuild_disc_list()
def _build_ui(self):
with dpg.window(
@@ -781,22 +876,17 @@ class App:
label="Discussion History",
tag="win_discussion",
pos=(824, 8),
width=400,
height=500,
width=420,
height=600,
no_close=True,
):
dpg.add_input_text(
tag="discussion_box",
default_value="\n---\n".join(self.history),
multiline=True,
width=-1,
height=-64,
)
dpg.add_separator()
with dpg.group(horizontal=True):
dpg.add_button(label="Add Separator", callback=self.cb_add_excerpt)
dpg.add_button(label="Clear", callback=self.cb_clear_discussion)
dpg.add_button(label="Save", callback=self.cb_save_discussion)
dpg.add_button(label="+ Entry", callback=self.cb_disc_append_entry)
dpg.add_button(label="Clear All", callback=self.cb_disc_clear)
dpg.add_button(label="Save", callback=self.cb_disc_save)
dpg.add_separator()
with dpg.child_window(tag="disc_scroll", height=-1, border=False):
pass
with dpg.window(
label="Provider",
@@ -846,6 +936,7 @@ class App:
dpg.add_button(label="Gen + Send", callback=self.cb_generate_send)
dpg.add_button(label="MD Only", callback=self.cb_md_only)
dpg.add_button(label="Reset", callback=self.cb_reset_session)
dpg.add_button(label="-> History", callback=self.cb_append_message_to_history)
with dpg.window(
label="Response",
@@ -860,8 +951,10 @@ class App:
multiline=True,
readonly=True,
width=-1,
height=-1,
height=-48,
)
dpg.add_separator()
dpg.add_button(label="-> History", callback=self.cb_append_response_to_history)
with dpg.window(
label="Tool Calls",