discussion history improvemnts
This commit is contained in:
@@ -130,3 +130,7 @@ Status line and colour legend live at the top of the Comms History window (above
|
||||
- Discussion history excerpts could be individually toggleable for inclusion in the generated md
|
||||
- `MAX_TOOL_ROUNDS` in `ai_client.py` caps agentic loops at 5 rounds; adjustable
|
||||
- `COMMS_CLAMP_CHARS` in `gui.py` controls the character threshold for clamping heavy payload fields in the Comms History panel
|
||||
|
||||
|
||||
**Discussion History panel (updated):**
|
||||
- **Discussion History** - structured block editor; each entry has a collapse toggle (-/+), a role combo (populated from disc_roles config list), and a multiline content field; per-entry buttons: Ins (insert before), Del (remove); global toolbar buttons: + Entry, -All (collapse all), +All (expand all), Clear All, Save; collapsible **Roles** sub-section lets you add/remove role names which are persisted to config.toml [discussion] roles; -> History buttons on Message and Response panels append the current message/response as a new entry (collapsed=False)
|
||||
@@ -63,7 +63,6 @@ history = [
|
||||
"AI:\nThe file has `\\r\\n` line endings mixed in. I'll write the replacement using a Python one-liner to avoid PowerShell line-ending issues:",
|
||||
"User:\nSure, if you want also enforce LF if you want on all files. I manually attempted so in vscode.",
|
||||
"AI:\nDoes work... (Noted by user)\n- Reponse:\nNow clean up the temp patch scripts and do a quick sanity check:",
|
||||
"User:\n",
|
||||
"User:\nLets add some theming to this. Add options to change the ui dpi scale and the font used, also add the ability to change the palette I guess. We can reference my 10x editor settings for inspiration:\n```\n[Omitted as its already been utilized]\n\n```",
|
||||
"AI:\nGood. Now I'll patch `gui.py` — adding the Theme window and wiring it up. I'll make targeted insertions rather than a full rewrite:\n\n1. Add `import theme` at the top\n2. Add `_build_theme_window()` and its callbacks to `App`\n3. Call `theme.load_from_config()` at startup (in `run()`)\n4. Call `theme.save_to_config()` in `_flush_to_config()`\n5. Add `win_theme` to `_build_ui()`",
|
||||
"User:\nSure lets patch gui.py.",
|
||||
@@ -72,6 +71,8 @@ history = [
|
||||
"AI:\nThe em-dash in the docstring differs. Let me match by a more robust regex:",
|
||||
"User:\nOk it seems fixed now... (themeing for fonts, nice job). \nNow lets do those adjustments to discussion history:\nIt'd also be nice if we can collapse the discussion entries indvidual and with a collapse/expand all button.\nAlso there is no way right now for me to define new roles for the discussion other than by editing the source.\nShould at least be configurable frm the config.toml...",
|
||||
"AI:\nGood, I have a clear picture. Here's the plan:\n\n**Changes needed:**\n1. **`config.toml`** — add `[discussion] roles = [...]` so roles are configurable\n2. **`gui.py`** — 4 targeted edits:\n - `DISC_ROLES` becomes a module-level fallback; the real list comes from config at load time and lives on `App`\n - `_parse_history_entries()` takes `roles` as a parameter\n - `_rebuild_disc_list()` — add collapse/expand per entry (using a `bool` `collapsed` flag in each dict), Collapse All / Expand All buttons in the toolbar\n - Add a \"Roles\" sub-section in the Discussion window for adding/removing role names from the config list, and wire it into `_flush_to_config()`\n\nI'll do this as a Python patch script to avoid PowerShell string escaping issues:",
|
||||
"User:\nSure, go ahead and make to those change patches and apply them.",
|
||||
"AI:\nAll 16 checks pass. Now update `MainContext.md` and clean up the patch file:\n(Note from user: the AI did so!)",
|
||||
]
|
||||
|
||||
[ai]
|
||||
|
||||
@@ -10,13 +10,13 @@ Collapsed=0
|
||||
|
||||
[Window][###22]
|
||||
Pos=0,0
|
||||
Size=374,239
|
||||
Size=609,326
|
||||
Collapsed=0
|
||||
DockId=0x0000002D,0
|
||||
DockId=0x0000002F,0
|
||||
|
||||
[Window][###30]
|
||||
Pos=0,654
|
||||
Size=374,696
|
||||
Size=609,696
|
||||
Collapsed=0
|
||||
DockId=0x00000027,0
|
||||
|
||||
@@ -62,9 +62,10 @@ Size=700,440
|
||||
Collapsed=0
|
||||
|
||||
[Window][###126]
|
||||
Pos=1578,868
|
||||
Size=700,440
|
||||
Pos=611,0
|
||||
Size=699,2137
|
||||
Collapsed=0
|
||||
DockId=0x00000031,0
|
||||
|
||||
[Window][###147]
|
||||
Pos=1578,868
|
||||
@@ -103,7 +104,7 @@ DockId=0x00000014,0
|
||||
Pos=2531,0
|
||||
Size=1309,1690
|
||||
Collapsed=0
|
||||
DockId=0x00000029,0
|
||||
DockId=0x00000032,0
|
||||
|
||||
[Window][###106]
|
||||
Pos=601,0
|
||||
@@ -112,10 +113,10 @@ Collapsed=0
|
||||
DockId=0x00000012,0
|
||||
|
||||
[Window][###100]
|
||||
Pos=2687,1049
|
||||
Size=1153,1088
|
||||
Pos=611,0
|
||||
Size=699,2137
|
||||
Collapsed=0
|
||||
DockId=0x0000002C,0
|
||||
DockId=0x00000031,1
|
||||
|
||||
[Window][###133]
|
||||
Pos=1306,785
|
||||
@@ -164,7 +165,7 @@ DockId=0x00000015,0
|
||||
Pos=551,0
|
||||
Size=1060,2137
|
||||
Collapsed=0
|
||||
DockId=0x00000029,1
|
||||
DockId=0x00000032,1
|
||||
|
||||
[Window][###110]
|
||||
Pos=2438,0
|
||||
@@ -216,15 +217,15 @@ DockId=0x00000012,0
|
||||
|
||||
[Window][###75]
|
||||
Pos=0,1352
|
||||
Size=374,785
|
||||
Size=609,785
|
||||
Collapsed=0
|
||||
DockId=0x00000022,0
|
||||
|
||||
[Window][###85]
|
||||
Pos=1320,0
|
||||
Size=1365,2137
|
||||
Pos=1312,0
|
||||
Size=1187,2137
|
||||
Collapsed=0
|
||||
DockId=0x00000029,0
|
||||
DockId=0x00000032,0
|
||||
|
||||
[Window][###92]
|
||||
Pos=376,0
|
||||
@@ -245,9 +246,10 @@ Collapsed=0
|
||||
DockId=0x00000012,2
|
||||
|
||||
[Window][###142]
|
||||
Pos=1578,868
|
||||
Size=700,440
|
||||
Pos=0,328
|
||||
Size=609,324
|
||||
Collapsed=0
|
||||
DockId=0x00000030,0
|
||||
|
||||
[Window][###244]
|
||||
Pos=1578,868
|
||||
@@ -300,7 +302,7 @@ DockId=0x00000028,0
|
||||
Pos=998,0
|
||||
Size=853,602
|
||||
Collapsed=0
|
||||
DockId=0x00000029,0
|
||||
DockId=0x00000032,0
|
||||
|
||||
[Window][###89]
|
||||
Pos=351,0
|
||||
@@ -470,8 +472,8 @@ Size=700,440
|
||||
Collapsed=0
|
||||
|
||||
[Window][###108]
|
||||
Pos=2687,0
|
||||
Size=1153,1047
|
||||
Pos=2501,0
|
||||
Size=1339,1331
|
||||
Collapsed=0
|
||||
DockId=0x0000002B,0
|
||||
|
||||
@@ -531,11 +533,50 @@ Pos=1578,868
|
||||
Size=700,440
|
||||
Collapsed=0
|
||||
|
||||
[Window][###2077]
|
||||
Pos=1578,868
|
||||
Size=1586,1128
|
||||
Collapsed=0
|
||||
|
||||
[Window][###2533]
|
||||
Pos=1578,868
|
||||
Size=1286,1051
|
||||
Collapsed=0
|
||||
|
||||
[Window][###2657]
|
||||
Pos=1578,868
|
||||
Size=700,440
|
||||
Collapsed=0
|
||||
|
||||
[Window][###2785]
|
||||
Pos=1578,868
|
||||
Size=700,440
|
||||
Collapsed=0
|
||||
|
||||
[Window][###2914]
|
||||
Pos=1578,868
|
||||
Size=700,440
|
||||
Collapsed=0
|
||||
|
||||
[Window][###116]
|
||||
Pos=2501,1333
|
||||
Size=1339,804
|
||||
Collapsed=0
|
||||
DockId=0x0000002C,0
|
||||
|
||||
[Window][###120]
|
||||
Pos=611,0
|
||||
Size=699,2137
|
||||
Collapsed=0
|
||||
DockId=0x00000031,2
|
||||
|
||||
[Docking][Data]
|
||||
DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,0 Size=3840,2137 Split=X Selected=0x40484D8F
|
||||
DockNode ID=0x00000003 Parent=0x7C6B3D9B SizeRef=374,1161 Split=Y Selected=0xEE087978
|
||||
DockNode ID=0x00000003 Parent=0x7C6B3D9B SizeRef=609,1161 Split=Y Selected=0xEE087978
|
||||
DockNode ID=0x00000005 Parent=0x00000003 SizeRef=235,354 Split=Y Selected=0xEE087978
|
||||
DockNode ID=0x0000002D Parent=0x00000005 SizeRef=374,239 Selected=0xEE087978
|
||||
DockNode ID=0x0000002D Parent=0x00000005 SizeRef=374,239 Split=Y Selected=0xEE087978
|
||||
DockNode ID=0x0000002F Parent=0x0000002D SizeRef=374,326 Selected=0xEE087978
|
||||
DockNode ID=0x00000030 Parent=0x0000002D SizeRef=374,324 Selected=0x69F9D389
|
||||
DockNode ID=0x0000002E Parent=0x00000005 SizeRef=374,411 Selected=0xFBBC1691
|
||||
DockNode ID=0x00000006 Parent=0x00000003 SizeRef=235,805 Split=Y Selected=0x5F94F9BD
|
||||
DockNode ID=0x00000009 Parent=0x00000006 SizeRef=235,453 Split=Y Selected=0x5F94F9BD
|
||||
@@ -546,7 +587,7 @@ DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,0 Size=384
|
||||
DockNode ID=0x00000022 Parent=0x0000001D SizeRef=549,785 Selected=0x0CE534DB
|
||||
DockNode ID=0x0000001E Parent=0x00000009 SizeRef=364,715 Selected=0xF475F06A
|
||||
DockNode ID=0x0000000A Parent=0x00000006 SizeRef=235,350 Selected=0x80199DAE
|
||||
DockNode ID=0x00000004 Parent=0x7C6B3D9B SizeRef=3464,1161 Split=X
|
||||
DockNode ID=0x00000004 Parent=0x7C6B3D9B SizeRef=3229,1161 Split=X
|
||||
DockNode ID=0x00000001 Parent=0x00000004 SizeRef=1060,1161 Split=Y Selected=0x40484D8F
|
||||
DockNode ID=0x00000007 Parent=0x00000001 SizeRef=595,492 Selected=0xBA13FCDE
|
||||
DockNode ID=0x00000008 Parent=0x00000001 SizeRef=595,1643 Split=X Selected=0x40484D8F
|
||||
@@ -558,16 +599,18 @@ DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,0 Size=384
|
||||
DockNode ID=0x00000017 Parent=0x00000013 SizeRef=1314,1749 Selected=0x4B454E0B
|
||||
DockNode ID=0x00000018 Parent=0x00000013 SizeRef=1309,1749 Split=Y Selected=0x88A8C2FF
|
||||
DockNode ID=0x00000019 Parent=0x00000018 SizeRef=2440,1412 Split=X Selected=0x88A8C2FF
|
||||
DockNode ID=0x00000023 Parent=0x00000019 SizeRef=1365,737 Split=Y Selected=0x4F935A1E
|
||||
DockNode ID=0x00000023 Parent=0x00000019 SizeRef=1888,737 Split=Y Selected=0x4F935A1E
|
||||
DockNode ID=0x0000001F Parent=0x00000023 SizeRef=2315,1191 Split=Y Selected=0x4F935A1E
|
||||
DockNode ID=0x00000025 Parent=0x0000001F SizeRef=2315,1244 Split=X Selected=0x4F935A1E
|
||||
DockNode ID=0x00000029 Parent=0x00000025 SizeRef=853,1867 CentralNode=1 Selected=0xFDB3860E
|
||||
DockNode ID=0x00000029 Parent=0x00000025 SizeRef=853,1867 Split=X Selected=0xFDB3860E
|
||||
DockNode ID=0x00000031 Parent=0x00000029 SizeRef=699,2137 Selected=0xC56063F4
|
||||
DockNode ID=0x00000032 Parent=0x00000029 SizeRef=1187,2137 CentralNode=1 Selected=0xFDB3860E
|
||||
DockNode ID=0x0000002A Parent=0x00000025 SizeRef=890,1867 Selected=0x40484D8F
|
||||
DockNode ID=0x00000026 Parent=0x0000001F SizeRef=2315,621 Selected=0x7D28643F
|
||||
DockNode ID=0x00000020 Parent=0x00000023 SizeRef=2315,944 Selected=0x4C2F06CB
|
||||
DockNode ID=0x00000024 Parent=0x00000019 SizeRef=1153,737 Split=Y Selected=0x88A8C2FF
|
||||
DockNode ID=0x0000002B Parent=0x00000024 SizeRef=1153,1047 Selected=0xB8D8893E
|
||||
DockNode ID=0x0000002C Parent=0x00000024 SizeRef=1153,1088 Selected=0x88A8C2FF
|
||||
DockNode ID=0x00000024 Parent=0x00000019 SizeRef=1339,737 Split=Y Selected=0xB8D8893E
|
||||
DockNode ID=0x0000002B Parent=0x00000024 SizeRef=1153,1331 Selected=0xB8D8893E
|
||||
DockNode ID=0x0000002C Parent=0x00000024 SizeRef=1153,804 Selected=0xCCB4E4FA
|
||||
DockNode ID=0x0000001A Parent=0x00000018 SizeRef=2440,723 Selected=0x3A881EEF
|
||||
DockNode ID=0x00000014 Parent=0x00000010 SizeRef=1967,445 Selected=0xC36FF36B
|
||||
DockNode ID=0x00000002 Parent=0x00000004 SizeRef=2227,1161 Split=X Selected=0x714F2F7B
|
||||
|
||||
122
gui.py
122
gui.py
@@ -287,36 +287,38 @@ class ConfirmDialog:
|
||||
DISC_ROLES = ["User", "AI", "Vendor API", "System"]
|
||||
|
||||
|
||||
def _parse_history_entries(history: list[str]) -> list[dict]:
|
||||
def _parse_history_entries(history: list[str], roles: list[str] | None = None) -> list[dict]:
|
||||
"""
|
||||
Convert the raw TOML string array into a flat list of {role, content} dicts.
|
||||
Convert the raw TOML string array into a flat list of {role, content, collapsed} dicts.
|
||||
Each TOML string is one excerpt (may contain multiple role blocks separated
|
||||
by lines like "Role:" or "[Role]"). We detect the common patterns:
|
||||
"User:\n..." "AI:\n..." "[User]\n..." "[AI]\n..."
|
||||
and split accordingly. Unrecognised text becomes a User entry.
|
||||
roles: list of known role strings (defaults to module DISC_ROLES if None).
|
||||
"""
|
||||
import re
|
||||
known = roles if roles is not None else DISC_ROLES
|
||||
entries: list[dict] = []
|
||||
role_pattern = re.compile(
|
||||
r'^(?:\[)?(' + '|'.join(re.escape(r) for r in DISC_ROLES) + r')(?:\])?:?\s*$',
|
||||
r'^(?:\[)?(' + '|'.join(re.escape(r) for r in known) + r')(?:\])?:?\s*$',
|
||||
re.IGNORECASE | re.MULTILINE,
|
||||
)
|
||||
for excerpt in history:
|
||||
# Find all role header positions
|
||||
splits = [(m.start(), m.end(), m.group(1).capitalize()) for m in role_pattern.finditer(excerpt)]
|
||||
splits = [(m.start(), m.end(), m.group(1)) for m in role_pattern.finditer(excerpt)]
|
||||
if not splits:
|
||||
# No role headers found - treat whole excerpt as User content
|
||||
text = excerpt.strip()
|
||||
if text:
|
||||
entries.append({"role": "User", "content": text})
|
||||
entries.append({"role": "User", "content": text, "collapsed": False})
|
||||
continue
|
||||
# Extract content between headers
|
||||
for idx, (start, end, role) in enumerate(splits):
|
||||
next_start = splits[idx + 1][0] if idx + 1 < len(splits) else len(excerpt)
|
||||
content = excerpt[end:next_start].strip()
|
||||
# Normalise role capitalisation to match DISC_ROLES
|
||||
matched = next((r for r in DISC_ROLES if r.lower() == role.lower()), role)
|
||||
entries.append({"role": matched, "content": content})
|
||||
# Normalise role capitalisation to match known list
|
||||
matched = next((r for r in known if r.lower() == role.lower()), role)
|
||||
entries.append({"role": matched, "content": content, "collapsed": False})
|
||||
return entries
|
||||
|
||||
class App:
|
||||
@@ -330,7 +332,10 @@ class App:
|
||||
self.config.get("discussion", {}).get("history", [])
|
||||
)
|
||||
|
||||
self.disc_entries: list[dict] = _parse_history_entries(self.history)
|
||||
self.disc_roles: list[str] = list(
|
||||
self.config.get("discussion", {}).get("roles", list(DISC_ROLES))
|
||||
)
|
||||
self.disc_entries: list[dict] = _parse_history_entries(self.history, self.disc_roles)
|
||||
|
||||
ai_cfg = self.config.get("ai", {})
|
||||
self.current_provider: str = ai_cfg.get("provider", "gemini")
|
||||
@@ -455,7 +460,7 @@ class App:
|
||||
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["discussion"] = {"history": self.history, "roles": self.disc_roles}
|
||||
self.config["ai"] = {
|
||||
"provider": self.current_provider,
|
||||
"model": self.current_model,
|
||||
@@ -711,23 +716,38 @@ class App:
|
||||
return
|
||||
dpg.delete_item("disc_scroll", children_only=True)
|
||||
for i, entry in enumerate(self.disc_entries):
|
||||
collapsed = entry.get("collapsed", False)
|
||||
preview = entry["content"].replace("\n", " ")[:60]
|
||||
if len(entry["content"]) > 60:
|
||||
preview += "..."
|
||||
with dpg.group(parent="disc_scroll"):
|
||||
with dpg.group(horizontal=True):
|
||||
dpg.add_button(
|
||||
tag=f"disc_toggle_{i}",
|
||||
label="+" if collapsed else "-",
|
||||
width=24,
|
||||
callback=self._make_disc_toggle_cb(i),
|
||||
)
|
||||
dpg.add_combo(
|
||||
tag=f"disc_role_{i}",
|
||||
items=DISC_ROLES,
|
||||
items=self.disc_roles,
|
||||
default_value=entry["role"],
|
||||
width=120,
|
||||
width=160,
|
||||
callback=self._make_disc_role_cb(i),
|
||||
)
|
||||
if collapsed:
|
||||
dpg.add_button(
|
||||
label="Insert Before",
|
||||
label="Ins",
|
||||
width=36,
|
||||
callback=self._make_disc_insert_cb(i),
|
||||
)
|
||||
dpg.add_button(
|
||||
label="Remove",
|
||||
label="Del",
|
||||
width=36,
|
||||
callback=self._make_disc_remove_cb(i),
|
||||
)
|
||||
dpg.add_text(preview, color=(160, 160, 150))
|
||||
with dpg.group(tag=f"disc_body_{i}", show=not collapsed):
|
||||
dpg.add_input_text(
|
||||
tag=f"disc_content_{i}",
|
||||
default_value=entry["content"],
|
||||
@@ -764,8 +784,62 @@ class App:
|
||||
self._rebuild_disc_list()
|
||||
return cb
|
||||
|
||||
def _make_disc_toggle_cb(self, idx: int):
|
||||
def cb():
|
||||
if idx < len(self.disc_entries):
|
||||
tag = f"disc_content_{idx}"
|
||||
if dpg.does_item_exist(tag):
|
||||
self.disc_entries[idx]["content"] = dpg.get_value(tag)
|
||||
self.disc_entries[idx]["collapsed"] = not self.disc_entries[idx].get("collapsed", False)
|
||||
self._rebuild_disc_list()
|
||||
return cb
|
||||
|
||||
def cb_disc_collapse_all(self):
|
||||
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)
|
||||
entry["collapsed"] = True
|
||||
self._rebuild_disc_list()
|
||||
|
||||
def cb_disc_expand_all(self):
|
||||
for entry in self.disc_entries:
|
||||
entry["collapsed"] = False
|
||||
self._rebuild_disc_list()
|
||||
|
||||
def _rebuild_disc_roles_list(self):
|
||||
if not dpg.does_item_exist("disc_roles_scroll"):
|
||||
return
|
||||
dpg.delete_item("disc_roles_scroll", children_only=True)
|
||||
for i, role in enumerate(self.disc_roles):
|
||||
with dpg.group(horizontal=True, parent="disc_roles_scroll"):
|
||||
dpg.add_button(
|
||||
label="x", width=24,
|
||||
callback=self._make_disc_remove_role_cb(i),
|
||||
)
|
||||
dpg.add_text(role)
|
||||
|
||||
def _make_disc_remove_role_cb(self, idx: int):
|
||||
def cb():
|
||||
if idx < len(self.disc_roles):
|
||||
self.disc_roles.pop(idx)
|
||||
self._rebuild_disc_roles_list()
|
||||
self._rebuild_disc_list()
|
||||
return cb
|
||||
|
||||
def cb_disc_add_role(self):
|
||||
if not dpg.does_item_exist("disc_new_role_input"):
|
||||
return
|
||||
name = dpg.get_value("disc_new_role_input").strip()
|
||||
if name and name not in self.disc_roles:
|
||||
self.disc_roles.append(name)
|
||||
dpg.set_value("disc_new_role_input", "")
|
||||
self._rebuild_disc_roles_list()
|
||||
self._rebuild_disc_list()
|
||||
|
||||
def cb_disc_append_entry(self):
|
||||
self.disc_entries.append({"role": "User", "content": ""})
|
||||
default_role = self.disc_roles[0] if self.disc_roles else "User"
|
||||
self.disc_entries.append({"role": default_role, "content": "", "collapsed": False})
|
||||
self._rebuild_disc_list()
|
||||
|
||||
def cb_disc_clear(self):
|
||||
@@ -785,13 +859,13 @@ class App:
|
||||
def cb_append_message_to_history(self):
|
||||
msg = dpg.get_value("ai_input")
|
||||
if msg:
|
||||
self.disc_entries.append({"role": "User", "content": msg})
|
||||
self.disc_entries.append({"role": "User", "content": msg, "collapsed": False})
|
||||
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.disc_entries.append({"role": "AI", "content": resp, "collapsed": False})
|
||||
self._rebuild_disc_list()
|
||||
|
||||
|
||||
@@ -971,9 +1045,22 @@ class App:
|
||||
):
|
||||
with dpg.group(horizontal=True):
|
||||
dpg.add_button(label="+ Entry", callback=self.cb_disc_append_entry)
|
||||
dpg.add_button(label="-All", callback=self.cb_disc_collapse_all)
|
||||
dpg.add_button(label="+All", callback=self.cb_disc_expand_all)
|
||||
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.collapsing_header(label="Roles", default_open=False):
|
||||
with dpg.child_window(tag="disc_roles_scroll", height=96, border=True):
|
||||
pass
|
||||
with dpg.group(horizontal=True):
|
||||
dpg.add_input_text(
|
||||
tag="disc_new_role_input",
|
||||
hint="New role name",
|
||||
width=-72,
|
||||
)
|
||||
dpg.add_button(label="Add", callback=self.cb_disc_add_role)
|
||||
dpg.add_separator()
|
||||
with dpg.child_window(tag="disc_scroll", height=-1, border=False):
|
||||
pass
|
||||
|
||||
@@ -1100,6 +1187,7 @@ class App:
|
||||
self._build_ui()
|
||||
theme.load_from_config(self.config)
|
||||
self._rebuild_disc_list()
|
||||
self._rebuild_disc_roles_list()
|
||||
self._fetch_models(self.current_provider)
|
||||
|
||||
while dpg.is_dearpygui_running():
|
||||
|
||||
Reference in New Issue
Block a user