Compare commits
2 Commits
ca8e33837b
...
6ae8737c1a
| Author | SHA1 | Date | |
|---|---|---|---|
| 6ae8737c1a | |||
| 92e7352d37 |
308
src/gui_2.py
308
src/gui_2.py
@@ -111,8 +111,8 @@ class App:
|
|||||||
self._editing_persona_max_tokens = 4096
|
self._editing_persona_max_tokens = 4096
|
||||||
self._editing_persona_tool_preset_id = ""
|
self._editing_persona_tool_preset_id = ""
|
||||||
self._editing_persona_bias_profile_id = ""
|
self._editing_persona_bias_profile_id = ""
|
||||||
self._editing_persona_preferred_models = "[]"
|
self._editing_persona_preferred_models_list: list[str] = []
|
||||||
self._editing_persona_tier_assignments = "{}"
|
self._editing_persona_scope = "project"
|
||||||
self._editing_persona_is_new = True
|
self._editing_persona_is_new = True
|
||||||
self._persona_editor_opened = False
|
self._persona_editor_opened = False
|
||||||
self._personas_list: dict[str, dict] = {}
|
self._personas_list: dict[str, dict] = {}
|
||||||
@@ -1233,112 +1233,201 @@ class App:
|
|||||||
def _render_persona_editor_modal(self) -> None:
|
def _render_persona_editor_modal(self) -> None:
|
||||||
if not self.show_persona_editor_modal: return
|
if not self.show_persona_editor_modal: return
|
||||||
imgui.open_popup("Persona Editor")
|
imgui.open_popup("Persona Editor")
|
||||||
|
imgui.set_next_window_size(imgui.ImVec2(800, 600), imgui.Cond_.first_use_ever)
|
||||||
opened, self.show_persona_editor_modal = imgui.begin_popup_modal("Persona Editor", self.show_persona_editor_modal)
|
opened, self.show_persona_editor_modal = imgui.begin_popup_modal("Persona Editor", self.show_persona_editor_modal)
|
||||||
if opened:
|
if opened:
|
||||||
try:
|
try:
|
||||||
imgui.text("Name:")
|
avail = imgui.get_content_region_avail()
|
||||||
imgui.same_line()
|
# Left Pane: List of Personas
|
||||||
imgui.push_item_width(200)
|
imgui.begin_child("persona_list_area", imgui.ImVec2(250, avail.y), True)
|
||||||
_, self._editing_persona_name = imgui.input_text("##pname", self._editing_persona_name, 128)
|
try:
|
||||||
imgui.pop_item_width()
|
if imgui.button("New Persona", imgui.ImVec2(-1, 0)):
|
||||||
imgui.text("Provider:")
|
self._editing_persona_name = ""
|
||||||
imgui.same_line()
|
self._editing_persona_provider = self.current_provider
|
||||||
providers = self.controller.PROVIDERS
|
self._editing_persona_model = self.current_model
|
||||||
p_idx = providers.index(self._editing_persona_provider) + 1 if self._editing_persona_provider in providers else 0
|
self._editing_persona_system_prompt = ""
|
||||||
imgui.push_item_width(120)
|
self._editing_persona_temperature = 0.7
|
||||||
_, p_idx = imgui.combo("##pprov", p_idx, ["None"] + providers)
|
self._editing_persona_max_tokens = 4096
|
||||||
self._editing_persona_provider = providers[p_idx - 1] if p_idx > 0 else ""
|
self._editing_persona_tool_preset_id = ""
|
||||||
imgui.pop_item_width()
|
self._editing_persona_bias_profile_id = ""
|
||||||
imgui.text("Model:")
|
self._editing_persona_preferred_models_list = []
|
||||||
all_models = self.controller.all_available_models.get(self._editing_persona_provider, [])
|
self._editing_persona_scope = "project"
|
||||||
if not all_models and self._editing_persona_model:
|
self._editing_persona_is_new = True
|
||||||
all_models = [self._editing_persona_model]
|
imgui.separator()
|
||||||
m_idx = all_models.index(self._editing_persona_model) + 1 if self._editing_persona_model in all_models else 0
|
personas = getattr(self.controller, 'personas', {})
|
||||||
imgui.push_item_width(150)
|
for name in sorted(personas.keys()):
|
||||||
_, m_idx = imgui.combo("##pmodel", m_idx, ["None"] + all_models)
|
is_sel = (name == self._editing_persona_name and not self._editing_persona_is_new)
|
||||||
self._editing_persona_model = all_models[m_idx - 1] if m_idx > 0 else ""
|
if imgui.selectable(name, is_sel)[0]:
|
||||||
imgui.pop_item_width()
|
p = personas[name]
|
||||||
imgui.text("Temp:")
|
self._editing_persona_name = p.name
|
||||||
imgui.same_line()
|
self._editing_persona_provider = p.provider or ""
|
||||||
_, self._editing_persona_temperature = imgui.slider_float("##ptemp", self._editing_persona_temperature, 0.0, 2.0)
|
self._editing_persona_model = p.model or ""
|
||||||
imgui.text("MaxTok:")
|
self._editing_persona_system_prompt = p.system_prompt or ""
|
||||||
imgui.same_line()
|
self._editing_persona_temperature = p.temperature if p.temperature is not None else 0.7
|
||||||
_, self._editing_persona_max_tokens = imgui.input_int("##pmaxt", self._editing_persona_max_tokens)
|
self._editing_persona_max_tokens = p.max_output_tokens if p.max_output_tokens is not None else 4096
|
||||||
|
self._editing_persona_tool_preset_id = p.tool_preset or ""
|
||||||
|
self._editing_persona_bias_profile_id = p.bias_profile or ""
|
||||||
|
self._editing_persona_preferred_models_list = list(p.preferred_models) if p.preferred_models else []
|
||||||
|
self._editing_persona_scope = self.controller.persona_manager.get_persona_scope(p.name)
|
||||||
|
self._editing_persona_is_new = False
|
||||||
|
finally:
|
||||||
|
imgui.end_child()
|
||||||
|
|
||||||
# Tool Preset
|
|
||||||
imgui.text("Tool Preset:")
|
|
||||||
imgui.same_line()
|
imgui.same_line()
|
||||||
preset_names = ["None"] + sorted(self.controller.tool_presets.keys())
|
|
||||||
t_idx = preset_names.index(self._editing_persona_tool_preset_id) if hasattr(self, '_editing_persona_tool_preset_id') and self._editing_persona_tool_preset_id in preset_names else 0
|
|
||||||
imgui.push_item_width(150)
|
|
||||||
_, t_idx = imgui.combo("##ptoolpreset", t_idx, preset_names)
|
|
||||||
self._editing_persona_tool_preset_id = preset_names[t_idx] if t_idx > 0 else None
|
|
||||||
imgui.pop_item_width()
|
|
||||||
imgui.same_line()
|
|
||||||
if imgui.button("Manage Tools##pm"):
|
|
||||||
self.show_tool_preset_manager_modal = True
|
|
||||||
|
|
||||||
# Bias Profile
|
# Right Pane: Editor
|
||||||
imgui.text("Bias Profile:")
|
imgui.begin_child("persona_edit_area", imgui.ImVec2(0, avail.y), False)
|
||||||
imgui.same_line()
|
try:
|
||||||
bias_names = ["None"] + sorted(self.controller.bias_profiles.keys())
|
header = "New Persona" if self._editing_persona_is_new else f"Editing Persona: {self._editing_persona_name}"
|
||||||
b_idx = bias_names.index(self._editing_persona_bias_profile_id) if hasattr(self, '_editing_persona_bias_profile_id') and self._editing_persona_bias_profile_id in bias_names else 0
|
imgui.text_colored(C_IN, header)
|
||||||
imgui.push_item_width(150)
|
imgui.separator()
|
||||||
_, b_idx = imgui.combo("##pbiasprofile", b_idx, bias_names)
|
|
||||||
self._editing_persona_bias_profile_id = bias_names[b_idx] if b_idx > 0 else None
|
imgui.text("Name:")
|
||||||
imgui.pop_item_width()
|
imgui.same_line()
|
||||||
|
_, self._editing_persona_name = imgui.input_text("##pname", self._editing_persona_name, 128)
|
||||||
imgui.text("Pref Models (comma-separated):")
|
|
||||||
_, self._editing_persona_preferred_models = imgui.input_text("##pprefmodels", self._editing_persona_preferred_models, 256)
|
imgui.text("Scope:")
|
||||||
|
if imgui.radio_button("Global##pscope", self._editing_persona_scope == "global"):
|
||||||
|
self._editing_persona_scope = "global"
|
||||||
|
imgui.same_line()
|
||||||
|
if imgui.radio_button("Project##pscope", self._editing_persona_scope == "project"):
|
||||||
|
self._editing_persona_scope = "project"
|
||||||
|
|
||||||
|
imgui.separator()
|
||||||
|
|
||||||
|
imgui.text("Provider:")
|
||||||
|
imgui.same_line()
|
||||||
|
providers = self.controller.PROVIDERS
|
||||||
|
p_idx = providers.index(self._editing_persona_provider) + 1 if self._editing_persona_provider in providers else 0
|
||||||
|
imgui.push_item_width(150)
|
||||||
|
_, p_idx = imgui.combo("##pprov", p_idx, ["None"] + providers)
|
||||||
|
self._editing_persona_provider = providers[p_idx - 1] if p_idx > 0 else ""
|
||||||
|
imgui.pop_item_width()
|
||||||
|
|
||||||
|
imgui.text("Model:")
|
||||||
|
imgui.same_line()
|
||||||
|
all_models = self.controller.all_available_models.get(self._editing_persona_provider, [])
|
||||||
|
if not all_models and self._editing_persona_model:
|
||||||
|
all_models = [self._editing_persona_model]
|
||||||
|
m_idx = all_models.index(self._editing_persona_model) + 1 if self._editing_persona_model in all_models else 0
|
||||||
|
imgui.push_item_width(200)
|
||||||
|
_, m_idx = imgui.combo("##pmodel", m_idx, ["None"] + all_models)
|
||||||
|
self._editing_persona_model = all_models[m_idx - 1] if m_idx > 0 else ""
|
||||||
|
imgui.pop_item_width()
|
||||||
|
|
||||||
|
imgui.text("Temp:")
|
||||||
|
imgui.same_line()
|
||||||
|
_, self._editing_persona_temperature = imgui.slider_float("##ptemp", self._editing_persona_temperature, 0.0, 2.0)
|
||||||
|
|
||||||
|
imgui.text("Max Output Tokens:")
|
||||||
|
imgui.same_line()
|
||||||
|
_, self._editing_persona_max_tokens = imgui.input_int("##pmaxt", self._editing_persona_max_tokens)
|
||||||
|
|
||||||
|
imgui.text("Tool Preset:")
|
||||||
|
imgui.same_line()
|
||||||
|
t_preset_names = ["None"] + sorted(self.controller.tool_presets.keys())
|
||||||
|
t_idx = t_preset_names.index(self._editing_persona_tool_preset_id) if self._editing_persona_tool_preset_id in t_preset_names else 0
|
||||||
|
imgui.push_item_width(200)
|
||||||
|
_, t_idx = imgui.combo("##ptoolpreset", t_idx, t_preset_names)
|
||||||
|
self._editing_persona_tool_preset_id = t_preset_names[t_idx] if t_idx > 0 else ""
|
||||||
|
imgui.pop_item_width()
|
||||||
|
|
||||||
|
imgui.text("Bias Profile:")
|
||||||
|
imgui.same_line()
|
||||||
|
bias_names = ["None"] + sorted(self.controller.bias_profiles.keys())
|
||||||
|
b_idx = bias_names.index(self._editing_persona_bias_profile_id) if self._editing_persona_bias_profile_id in bias_names else 0
|
||||||
|
imgui.push_item_width(200)
|
||||||
|
_, b_idx = imgui.combo("##pbiasprofile", b_idx, bias_names)
|
||||||
|
self._editing_persona_bias_profile_id = bias_names[b_idx] if b_idx > 0 else ""
|
||||||
|
imgui.pop_item_width()
|
||||||
|
|
||||||
|
imgui.separator()
|
||||||
|
imgui.text("Preferred Models:")
|
||||||
|
to_remove = []
|
||||||
|
for i, model in enumerate(self._editing_persona_preferred_models_list):
|
||||||
|
imgui.text(f"- {model}")
|
||||||
|
imgui.same_line()
|
||||||
|
if imgui.button(f"x##pref_rem_{i}"):
|
||||||
|
to_remove.append(i)
|
||||||
|
for i in reversed(to_remove):
|
||||||
|
self._editing_persona_preferred_models_list.pop(i)
|
||||||
|
|
||||||
|
# Add Preferred Model
|
||||||
|
all_possible_models = []
|
||||||
|
for prov_models in self.controller.all_available_models.values():
|
||||||
|
all_possible_models.extend(prov_models)
|
||||||
|
all_possible_models = sorted(list(set(all_possible_models)))
|
||||||
|
|
||||||
|
if not hasattr(self, "_add_pref_model_idx"): self._add_pref_model_idx = 0
|
||||||
|
imgui.push_item_width(200)
|
||||||
|
_, self._add_pref_model_idx = imgui.combo("Add Preferred Model##add_pref", self._add_pref_model_idx, ["Select Model..."] + all_possible_models)
|
||||||
|
imgui.pop_item_width()
|
||||||
|
if self._add_pref_model_idx > 0:
|
||||||
|
new_m = all_possible_models[self._add_pref_model_idx - 1]
|
||||||
|
if new_m not in self._editing_persona_preferred_models_list:
|
||||||
|
self._editing_persona_preferred_models_list.append(new_m)
|
||||||
|
self._add_pref_model_idx = 0
|
||||||
|
|
||||||
|
imgui.separator()
|
||||||
|
imgui.text("System Prompt:")
|
||||||
|
|
||||||
|
# Load Prompt Preset
|
||||||
|
imgui.text("Load from Preset:")
|
||||||
|
imgui.same_line()
|
||||||
|
prompt_presets = ["Select..."] + sorted(self.controller.presets.keys())
|
||||||
|
if not hasattr(self, "_load_preset_idx"): self._load_preset_idx = 0
|
||||||
|
imgui.push_item_width(150)
|
||||||
|
_, self._load_preset_idx = imgui.combo("##load_preset", self._load_preset_idx, prompt_presets)
|
||||||
|
imgui.pop_item_width()
|
||||||
|
imgui.same_line()
|
||||||
|
if imgui.button("Apply##apply_p"):
|
||||||
|
if self._load_preset_idx > 0:
|
||||||
|
pname = prompt_presets[self._load_preset_idx]
|
||||||
|
if pname in self.controller.presets:
|
||||||
|
p = self.controller.presets[pname]
|
||||||
|
self._editing_persona_system_prompt = p.system_prompt
|
||||||
|
if p.temperature is not None: self._editing_persona_temperature = p.temperature
|
||||||
|
if p.max_output_tokens is not None: self._editing_persona_max_tokens = p.max_output_tokens
|
||||||
|
self._load_preset_idx = 0
|
||||||
|
|
||||||
imgui.text("Load Prompt Preset:")
|
_, self._editing_persona_system_prompt = imgui.input_text_multiline("##pprompt", self._editing_persona_system_prompt, imgui.ImVec2(-1, 150))
|
||||||
imgui.same_line()
|
|
||||||
prompt_presets = ["None"] + sorted(self.controller.presets.keys())
|
imgui.separator()
|
||||||
imgui.push_item_width(150)
|
if imgui.button("Save Persona", imgui.ImVec2(120, 0)):
|
||||||
changed_pr, pr_idx = imgui.combo("##load_prompt_preset", 0, prompt_presets)
|
if self._editing_persona_name.strip():
|
||||||
imgui.pop_item_width()
|
try:
|
||||||
if changed_pr and pr_idx > 0:
|
persona = models.Persona(
|
||||||
pname = prompt_presets[pr_idx]
|
name=self._editing_persona_name.strip(),
|
||||||
if pname in self.controller.presets:
|
provider=self._editing_persona_provider or None,
|
||||||
p = self.controller.presets[pname]
|
model=self._editing_persona_model or None,
|
||||||
self._editing_persona_system_prompt = p.system_prompt
|
system_prompt=self._editing_persona_system_prompt,
|
||||||
if p.temperature is not None: self._editing_persona_temperature = p.temperature
|
temperature=self._editing_persona_temperature,
|
||||||
if p.max_output_tokens is not None: self._editing_persona_max_tokens = p.max_output_tokens
|
max_output_tokens=self._editing_persona_max_tokens,
|
||||||
imgui.same_line()
|
tool_preset=self._editing_persona_tool_preset_id or None,
|
||||||
if imgui.button("Manage Prompts##pm"):
|
bias_profile=self._editing_persona_bias_profile_id or None,
|
||||||
self.show_preset_manager_modal = True
|
preferred_models=self._editing_persona_preferred_models_list,
|
||||||
|
)
|
||||||
imgui.text("Prompt:")
|
self.controller._cb_save_persona(persona, self._editing_persona_scope)
|
||||||
_, self._editing_persona_system_prompt = imgui.input_text_multiline("##pprompt", self._editing_persona_system_prompt, imgui.ImVec2(350, 50))
|
self.ai_status = f"Saved Persona: {persona.name}"
|
||||||
if imgui.button("Save##p", imgui.ImVec2(80, 0)):
|
except Exception as e:
|
||||||
if self._editing_persona_name.strip():
|
self.ai_status = f"Error saving persona: {e}"
|
||||||
try:
|
else:
|
||||||
pref_models = [m.strip() for m in self._editing_persona_preferred_models.split(",") if m.strip()]
|
self.ai_status = "Name required"
|
||||||
if self._editing_persona_preferred_models.strip() == "[]":
|
|
||||||
pref_models = []
|
imgui.same_line()
|
||||||
persona = models.Persona(
|
if imgui.button("Delete", imgui.ImVec2(100, 0)):
|
||||||
name=self._editing_persona_name.strip(),
|
if not self._editing_persona_is_new and self._editing_persona_name:
|
||||||
provider=self._editing_persona_provider or None,
|
self.controller._cb_delete_persona(self._editing_persona_name, self._editing_persona_scope)
|
||||||
model=self._editing_persona_model or None,
|
self.ai_status = f"Deleted Persona: {self._editing_persona_name}"
|
||||||
system_prompt=self._editing_persona_system_prompt,
|
self._editing_persona_name = ""
|
||||||
temperature=self._editing_persona_temperature,
|
self._editing_persona_is_new = True
|
||||||
max_output_tokens=self._editing_persona_max_tokens,
|
|
||||||
tool_preset=getattr(self, '_editing_persona_tool_preset_id', None),
|
imgui.same_line()
|
||||||
bias_profile=getattr(self, '_editing_persona_bias_profile_id', None),
|
if imgui.button("Close", imgui.ImVec2(100, 0)):
|
||||||
preferred_models=pref_models,
|
self.show_persona_editor_modal = False
|
||||||
)
|
imgui.close_current_popup()
|
||||||
self.controller._cb_save_persona(persona, "project")
|
finally:
|
||||||
self.ai_status = f"Saved: {persona.name}"
|
imgui.end_child()
|
||||||
self.show_persona_editor_modal = False
|
|
||||||
imgui.close_current_popup()
|
|
||||||
except Exception as e:
|
|
||||||
self.ai_status = f"Error: {e}"
|
|
||||||
else:
|
|
||||||
self.ai_status = "Name required"
|
|
||||||
imgui.same_line()
|
|
||||||
if imgui.button("Cancel##p", imgui.ImVec2(80, 0)):
|
|
||||||
self.show_persona_editor_modal = False
|
|
||||||
imgui.close_current_popup()
|
|
||||||
finally:
|
finally:
|
||||||
imgui.end_popup()
|
imgui.end_popup()
|
||||||
|
|
||||||
@@ -2184,19 +2273,20 @@ def hello():
|
|||||||
ai_client.set_bias_profile(persona.bias_profile)
|
ai_client.set_bias_profile(persona.bias_profile)
|
||||||
imgui.end_combo()
|
imgui.end_combo()
|
||||||
imgui.same_line()
|
imgui.same_line()
|
||||||
if imgui.button("Edit##persona"):
|
if imgui.button("Manage Personas"):
|
||||||
|
self.show_persona_editor_modal = True
|
||||||
if self.ui_active_persona and self.ui_active_persona in personas:
|
if self.ui_active_persona and self.ui_active_persona in personas:
|
||||||
persona = personas[self.ui_active_persona]
|
persona = personas[self.ui_active_persona]
|
||||||
self._editing_persona_name = persona.name
|
self._editing_persona_name = persona.name
|
||||||
self._editing_persona_provider = persona.provider or ""
|
self._editing_persona_provider = persona.provider or ""
|
||||||
self._editing_persona_model = persona.model or ""
|
self._editing_persona_model = persona.model or ""
|
||||||
self._editing_persona_system_prompt = persona.system_prompt or ""
|
self._editing_persona_system_prompt = persona.system_prompt or ""
|
||||||
self._editing_persona_temperature = persona.temperature or 0.7
|
self._editing_persona_temperature = persona.temperature if persona.temperature is not None else 0.7
|
||||||
self._editing_persona_max_tokens = persona.max_output_tokens or 4096
|
self._editing_persona_max_tokens = persona.max_output_tokens if persona.max_output_tokens is not None else 4096
|
||||||
self._editing_persona_tool_preset_id = persona.tool_preset or ""
|
self._editing_persona_tool_preset_id = persona.tool_preset or ""
|
||||||
self._editing_persona_bias_profile_id = persona.bias_profile or ""
|
self._editing_persona_bias_profile_id = persona.bias_profile or ""
|
||||||
import json
|
self._editing_persona_preferred_models_list = list(persona.preferred_models) if persona.preferred_models else []
|
||||||
self._editing_persona_preferred_models = json.dumps(persona.preferred_models) if persona.preferred_models else "[]"
|
self._editing_persona_scope = self.controller.persona_manager.get_persona_scope(persona.name)
|
||||||
self._editing_persona_is_new = False
|
self._editing_persona_is_new = False
|
||||||
else:
|
else:
|
||||||
self._editing_persona_name = ""
|
self._editing_persona_name = ""
|
||||||
@@ -2207,11 +2297,9 @@ def hello():
|
|||||||
self._editing_persona_max_tokens = 4096
|
self._editing_persona_max_tokens = 4096
|
||||||
self._editing_persona_tool_preset_id = ""
|
self._editing_persona_tool_preset_id = ""
|
||||||
self._editing_persona_bias_profile_id = ""
|
self._editing_persona_bias_profile_id = ""
|
||||||
self._editing_persona_preferred_models = "[]"
|
self._editing_persona_preferred_models_list = []
|
||||||
self._editing_persona_tier_assignments = "{}"
|
self._editing_persona_scope = "project"
|
||||||
self._editing_persona_is_new = True
|
self._editing_persona_is_new = True
|
||||||
self.show_persona_editor_modal = True
|
|
||||||
|
|
||||||
if self.current_provider == "gemini_cli":
|
if self.current_provider == "gemini_cli":
|
||||||
imgui.separator()
|
imgui.separator()
|
||||||
imgui.text("Gemini CLI")
|
imgui.text("Gemini CLI")
|
||||||
|
|||||||
@@ -47,6 +47,21 @@ class PersonaManager:
|
|||||||
data["personas"][persona.name] = persona.to_dict()
|
data["personas"][persona.name] = persona.to_dict()
|
||||||
self._save_file(path, data)
|
self._save_file(path, data)
|
||||||
|
|
||||||
|
def get_persona_scope(self, name: str) -> str:
|
||||||
|
"""Returns the scope ('global' or 'project') of a persona by name."""
|
||||||
|
if self.project_root:
|
||||||
|
project_path = paths.get_project_personas_path(self.project_root)
|
||||||
|
project_data = self._load_file(project_path)
|
||||||
|
if name in project_data.get("personas", {}):
|
||||||
|
return "project"
|
||||||
|
|
||||||
|
global_path = paths.get_global_personas_path()
|
||||||
|
global_data = self._load_file(global_path)
|
||||||
|
if name in global_data.get("personas", {}):
|
||||||
|
return "global"
|
||||||
|
|
||||||
|
return "project"
|
||||||
|
|
||||||
def delete_persona(self, name: str, scope: str = "project") -> None:
|
def delete_persona(self, name: str, scope: str = "project") -> None:
|
||||||
path = self._get_path(scope)
|
path = self._get_path(scope)
|
||||||
data = self._load_file(path)
|
data = self._load_file(path)
|
||||||
|
|||||||
Reference in New Issue
Block a user