feat(tui): add persistent header showing runtime/mode/target and keep it updated

This commit is contained in:
giveen
2026-01-20 12:34:08 -07:00
parent 6b4a568479
commit cabae0fcd6

View File

@@ -1228,6 +1228,9 @@ class PentestAgentTUI(App):
with Horizontal(id="main-container"):
# Chat area (left side)
with Vertical(id="chat-area"):
# Persistent header shown above the chat scroll so operator
# always sees runtime/mode/target information.
yield Static("", id="header")
yield ScrollableContainer(id="chat-scroll")
yield StatusBar(id="status-bar")
with Horizontal(id="input-container"):
@@ -1380,15 +1383,28 @@ class PentestAgentTUI(App):
tools_str += f", +{len(self.all_tools) - 5} more"
runtime_str = "Docker" if self.use_docker else "Local"
self._add_system(
f"+ PentestAgent ready\n"
f" Model: {self.model} | Tools: {len(self.all_tools)} | MCP: {mcp_server_count} | RAG: {rag_doc_count}\n"
f" Runtime: {runtime_str} | Mode: Assist (use /agent or /crew for autonomous modes)"
)
# Update persistent header instead of adding an ad-hoc system
# message to the chat. This keeps the info visible at top.
try:
self._update_header(model_line=(
f"+ PentestAgent ready\n"
f" Model: {self.model} | Tools: {len(self.all_tools)} | MCP: {mcp_server_count} | RAG: {rag_doc_count}\n"
f" Runtime: {runtime_str} | Mode: Assist (use /agent or /crew for autonomous modes)"
))
except Exception:
# Fallback to previous behavior if header widget isn't available
self._add_system(
f"+ PentestAgent ready\n"
f" Model: {self.model} | Tools: {len(self.all_tools)} | MCP: {mcp_server_count} | RAG: {rag_doc_count}\n"
f" Runtime: {runtime_str} | Mode: Assist (use /agent or /crew for autonomous modes)"
)
# Show target if provided (but don't auto-start)
# Also update header with target if present
if self.target:
self._add_system(f" Target: {self.target}")
try:
self._update_header(target=self.target)
except Exception:
self._add_system(f" Target: {self.target}")
except Exception as e:
import traceback
@@ -2408,6 +2424,39 @@ Be concise. Use the actual data from notes."""
scroll.mount(msg)
except Exception:
self._add_system(f" Target: {target}")
except Exception as e:
logging.getLogger(__name__).exception("Failed updating in-scroll target display: %s", e)
# Also update the persistent header so the target is always visible
try:
self._update_header(target=target)
except Exception:
pass
def _update_header(self, model_line: Optional[str] = None, target: Optional[str] = None) -> None:
"""Compose and update the persistent header widget."""
try:
header = self.query_one("#header", Static)
# Build header text from provided pieces or current state
lines: List[str] = []
if model_line:
lines.append(model_line)
else:
# try to recreate a compact model/runtime line
runtime_str = "Docker" if getattr(self, "use_docker", False) else "Local"
tools_count = len(getattr(self, "all_tools", [])) if hasattr(self, "all_tools") else 0
lines.append(
f"+ PentestAgent ready\n Model: {getattr(self, 'model', '')} | Tools: {tools_count} | RAG: {getattr(self, 'rag_doc_count', '')}\n Runtime: {runtime_str} | Mode: {getattr(self, '_mode', 'assist')}"
)
# Ensure target line is present/updated
if target is None:
target = getattr(self, "target", "")
if target:
# append target on its own line
lines.append(f" Target: {target}")
header.update("\n".join(lines))
except Exception:
pass
except Exception:
self._add_system(f" Target: {target}")