Update TUI
This commit is contained in:
parent
0383410c84
commit
6703468dd8
@ -76,7 +76,7 @@ ACTIONS = {
|
||||
},
|
||||
"send_prompt": {
|
||||
"key": KEY_CTRL_ENTER,
|
||||
"label": "Send Prompt", "mnemonic": "P", "shortcut": "Ctrl+Enter",
|
||||
"label": "Send Prompt", "mnemonic": "P", "shortcut": "Ctrl+Return",
|
||||
"handler": _send_prompt, "enabled": _ready,
|
||||
},
|
||||
"cancel_inference": {
|
||||
|
||||
@ -24,6 +24,10 @@ class HendrikTUI:
|
||||
self.agent_max_iterations = agent_max_iterations
|
||||
self.character_name = config.AGENT_CHARACTER or "AI Agent"
|
||||
|
||||
# Nama model set aktif (dipakai status bar). Diisi dari default set
|
||||
# saat startup, lalu diperbarui setiap kali user ganti model set.
|
||||
self.model_set_name = self._lookup_model_set_name()
|
||||
|
||||
self.messages = None
|
||||
self.log = []
|
||||
self.input_buffer = [""]
|
||||
@ -47,6 +51,31 @@ class HendrikTUI:
|
||||
self.session_mgr = NeoSessionManager()
|
||||
self.current_session: NeoSession | None = None
|
||||
|
||||
def _lookup_model_set_name(self) -> str:
|
||||
"""Nama model set yang sedang aktif (untuk status bar).
|
||||
|
||||
Mulai dari default set tipe 'llm'; jika model yang sedang dipakai
|
||||
ternyata milik set lain, cari set yang memuat model tersebut."""
|
||||
try:
|
||||
default_id = moop.get_default_set_id(None, "llm")
|
||||
default_set = moop.get_set(None, default_id) if default_id else None
|
||||
model = getattr(self.llm, "model", "") or ""
|
||||
if default_set and (
|
||||
not model
|
||||
or model in {c["model"] for c in moop.resolve_chain(None, default_id)}
|
||||
):
|
||||
return default_set["name"] or "-"
|
||||
if default_set:
|
||||
for cand in moop.list_sets(None):
|
||||
if cand["id"] == default_id:
|
||||
continue
|
||||
if model in {c["model"] for c in moop.resolve_chain(None, cand["id"])}:
|
||||
return cand["name"] or "-"
|
||||
return default_set["name"] or "-"
|
||||
return "-"
|
||||
except Exception:
|
||||
return "-"
|
||||
|
||||
def switch_model_set(self, set_id):
|
||||
default_chain = moop.default_chain(None, "llm")
|
||||
target = moop.get_set(None, set_id)
|
||||
@ -59,6 +88,7 @@ class HendrikTUI:
|
||||
if not default_chain:
|
||||
moop.set_default(None, "llm", set_id)
|
||||
self.llm.set_chains({"llm": chain})
|
||||
self.model_set_name = target.get("name") or self._lookup_model_set_name()
|
||||
if self.current_session:
|
||||
self.session_mgr.update_model_info(
|
||||
self.current_session.doc_id, self._model_info()
|
||||
|
||||
@ -9,6 +9,7 @@ import json
|
||||
from tools.coder import get_current_workspace
|
||||
|
||||
from . import theme
|
||||
from .actions import ACTIONS
|
||||
from .menubar import draw_menubar, draw_menu_dropdown
|
||||
|
||||
# Alias warna agar kode drawing di bawah tetap ringkas.
|
||||
@ -16,6 +17,7 @@ C_USER = theme.C_USER
|
||||
C_AI = theme.C_AI
|
||||
C_SYSTEM = theme.C_SYSTEM
|
||||
C_INPUT = theme.C_INPUT
|
||||
C_STATUS = theme.C_STATUS
|
||||
C_STATUS_READY = theme.C_STATUS_READY
|
||||
C_STATUS_PROC = theme.C_STATUS_PROC
|
||||
C_ERROR = theme.C_ERROR
|
||||
@ -344,55 +346,66 @@ def draw_input(app, stdscr):
|
||||
|
||||
|
||||
def draw_status(app, stdscr):
|
||||
# Status bar di baris h-9: mode, model, workspace, session
|
||||
# Status bar di baris h-9.
|
||||
# kiri : "STATUS nama_model_set nama_model workspace"
|
||||
# kanan : "nama_character Ctrl+Return:Send"
|
||||
# STATUS = mode READY/PROCESSING (berwarna). Bila terminal sempit, bagian
|
||||
# workspace dipotong dari depan (sisa akhir path) agar sisi kanan utuh.
|
||||
h, w = app.h, app.w
|
||||
y = h - 9
|
||||
ws = get_current_workspace()
|
||||
|
||||
session_tag = ""
|
||||
if app.current_session:
|
||||
session_tag = f" {app.current_session.name} "
|
||||
|
||||
model = app.llm.model
|
||||
mode = " PROCESSING " if app.processing else " READY "
|
||||
set_name = (getattr(app, "model_set_name", "") or "-").strip() or "-"
|
||||
model = (app.llm.model or "-").strip() or "-"
|
||||
ws = get_current_workspace() or "-"
|
||||
|
||||
# Format: [MODE] model workspace session (menggunakan spasi sebagai pemisah)
|
||||
status_text = f"{mode} {model} {ws} {session_tag}"
|
||||
send_key = ACTIONS["send_prompt"].get("shortcut") or "Ctrl+Return"
|
||||
right = f" {app.character_name} {send_key}:Send "
|
||||
|
||||
# Jika terlalu panjang, potong bagian workspace-nya saja agar tetap readable
|
||||
# Sisi kiri hanya boleh memakai ruang selebar w - len(right) - 1 (pemisah).
|
||||
avail = max(0, w - len(right) - 1)
|
||||
fixed = len(mode) + len(set_name) + len(model) + 3 # 3 = spasi pemisah
|
||||
ws_display = ws
|
||||
if len(status_text) > w:
|
||||
max_ws_len = w - len(mode) - len(model) - len(session_tag) - 3
|
||||
if len(ws) > max_ws_len:
|
||||
ws_display = ".." + ws[-(max_ws_len - 2):]
|
||||
status_text = f"{mode} {model} {ws_display} {session_tag}"
|
||||
if fixed + len(ws_display) > avail:
|
||||
budget = max(0, avail - fixed)
|
||||
ws_display = (".." + ws)[-budget:] if budget > 0 else ""
|
||||
|
||||
# Gambar background dasar
|
||||
full_status = status_text.ljust(w)[:w]
|
||||
stdscr.addstr(y, 0, full_status, curses.color_pair(C_STATUS_INFO))
|
||||
left = f"{mode} {set_name} {model} {ws_display}"[:avail]
|
||||
|
||||
def _clip(text, x):
|
||||
# Potong teks agar tidak melewati batas area kiri (kolom `avail`).
|
||||
if x >= avail:
|
||||
return ""
|
||||
return text[: avail - x]
|
||||
|
||||
# Background penuh sepanjang baris
|
||||
try:
|
||||
stdscr.addstr(y, 0, " " * w, curses.color_pair(C_STATUS_INFO))
|
||||
except curses.error:
|
||||
pass
|
||||
|
||||
# Highlight mode dengan warna berbeda (Hijau/Kuning)
|
||||
mode_attr = curses.color_pair(C_STATUS_READY) if not app.processing else curses.color_pair(C_STATUS_PROC)
|
||||
stdscr.addstr(y, 0, mode, mode_attr | curses.A_BOLD)
|
||||
|
||||
# Highlight Model, Workspace dan Session dengan warna Putih-Bold
|
||||
highlight_attr = curses.color_pair(C_STATUS_INFO) | curses.A_BOLD
|
||||
|
||||
try:
|
||||
# Mode sudah digambar, kita cari posisi setelah mode
|
||||
model_start = len(mode) + 1 # melewati mode + 1 spasi
|
||||
ws_start = len(mode) + len(model) + 2
|
||||
ws_len = len(ws_display)
|
||||
|
||||
# Gambar Model
|
||||
stdscr.addstr(y, model_start, model, highlight_attr)
|
||||
|
||||
# Gambar Workspace
|
||||
stdscr.addstr(y, ws_start, ws_display, highlight_attr)
|
||||
|
||||
# Gambar Session
|
||||
session_start = ws_start + ws_len + 1 # melewati workspace + 1 spasi
|
||||
if session_tag:
|
||||
stdscr.addstr(y, session_start, session_tag, highlight_attr)
|
||||
stdscr.addstr(y, 0, left, highlight_attr)
|
||||
# Mode ditimpa lebih dulu dengan warnanya sendiri
|
||||
stdscr.addstr(y, 0, mode, mode_attr | curses.A_BOLD)
|
||||
# Posisi model set, model, dan workspace (mengikuti isi `left`)
|
||||
set_start = len(mode) + 1
|
||||
stdscr.addstr(y, set_start, _clip(set_name, set_start), highlight_attr)
|
||||
model_start = set_start + len(set_name) + 1
|
||||
stdscr.addstr(y, model_start, _clip(model, model_start), highlight_attr)
|
||||
ws_start = model_start + len(model) + 1
|
||||
if ws_display:
|
||||
stdscr.addstr(y, ws_start, _clip(ws_display, ws_start), highlight_attr)
|
||||
except curses.error:
|
||||
pass
|
||||
|
||||
# Sisi kanan: character + petunjuk tombol kirim
|
||||
right_attr = curses.color_pair(C_STATUS) | curses.A_BOLD
|
||||
try:
|
||||
stdscr.addstr(y, w - len(right), right, right_attr)
|
||||
except curses.error:
|
||||
pass
|
||||
|
||||
@ -10,7 +10,7 @@ C_USER = 2 # user message: cyan
|
||||
C_AI = 3 # AI response: hijau
|
||||
C_SYSTEM = 4 # system log: kuning
|
||||
C_INPUT = 5 # text input: putih
|
||||
C_STATUS = 6 # status bar: hitam di atas kuning
|
||||
C_STATUS = 6 # status bar: hitam di atas biru
|
||||
C_STATUS_READY = 10 # status READY: hijau
|
||||
C_STATUS_PROC = 11 # status PROCESSING: kuning
|
||||
C_SEP = 7 # separator line: magenta
|
||||
@ -38,7 +38,7 @@ def init_colors():
|
||||
curses.init_pair(C_AI, curses.COLOR_GREEN, -1)
|
||||
curses.init_pair(C_SYSTEM, curses.COLOR_YELLOW, -1)
|
||||
curses.init_pair(C_INPUT, curses.COLOR_WHITE, -1)
|
||||
curses.init_pair(C_STATUS, curses.COLOR_BLACK, curses.COLOR_YELLOW)
|
||||
curses.init_pair(C_STATUS, curses.COLOR_BLACK, curses.COLOR_BLUE)
|
||||
curses.init_pair(C_STATUS_READY, curses.COLOR_BLACK, curses.COLOR_GREEN + 8)
|
||||
curses.init_pair(C_STATUS_PROC, curses.COLOR_BLACK, curses.COLOR_YELLOW)
|
||||
curses.init_pair(C_STATUS_INFO, curses.COLOR_BLACK, curses.COLOR_WHITE)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user