NOTICE: All information contained herein is, and remains
the property of TechnoCore Automate.
The ObjConversationTui.py module provides a
fullscreen Rich TUI for testing conversation flows
from the terminal. It implements the conversation
engine interface for styled rendering and includes a
chat CLI command that drives a fullscreen REPL with
inline character-by-character input.
The module contains two engine classes and four
fullscreen widget classes:
Engine Classes:
ConversationInterface -- Renders conversation
pages using Rich panels, tables, and styled text.
Loaded by the conversation factory when the engine
is set to TUI.
ConversationBroker -- Minimal stub following
the broker pattern.
Fullscreen Widget Classes (__rich__() protocol):
TuiHeader -- Header bar with bot icon,
conversation code, and contact ID.
TuiContext -- Context panel showing page
number, contact, and input field state.
TuiContent -- Main content area with header
text, options, prompts, and overlay panels for
help and error display.
TuiFooter -- Footer bar with keyboard command
hints, page indicator, and inline command input
with blinking cursor.
| Method | Purpose |
|---|---|
transmit_message(message) |
Print message via Rich Console |
display_context(opts) |
Render context state as a dim panel with field table |
display_options(opts) |
Render page header panel and options table; populate _TUI_STATE; return (first_key, first_prompt) |
_render_page(conv) |
Create ephemeral engine, render context/options, set expect/first_key on context |
_sync_widgets(conv, ...) |
Push _TUI_STATE data into the four widget objects |
_read_line(live, layout, footer) |
Read input character-by-character in cbreak mode, updating footer live |
The module-level _TUI_STATE dictionary bridges
state between the ephemeral engine instance (created
during read_conversation()) and the fullscreen
layout (which renders after read_conversation()
returns).
_TUI_STATE = {
"header": "", # Page header text
"options": [], # [(command, show), ...]
"prompts": [], # [(name, value), ...]
"first_key": "", # Context key for first prompt
"first_prompt": "", # Label for first prompt
}
The TUI uses rich.layout.Layout with
rich.live.Live(screen=True) for a fullscreen
terminal application. Input is captured
character-by-character using tty.setcbreak() and
os.read(), keeping the fullscreen layout active
at all times.
+===============================================+
| HEADER (size=3) |
| 🤖 Axion TUI 💬 Axion 👤 vheyn |
+-----------------------------------------------+
| CONTEXT (size=6) |
| 📋 Context |
| 📍 Page 1 │ 👤 vheyn |
| ✅ Name: John ✅ Email: j@x.com |
+-----------------------------------------------+
| CONTENT (ratio=1) |
| 💬 Conversation |
| |
| 💬 Welcome to the Rewards Platform! |
| Please select the number in your response. |
| |
| 📋 Options: |
| [1] 🎁 Redemption |
| [2] 🔒 Terms and Conditions |
| |
| ✏️ Prompts: |
| ⌨️ Email address ··· |
+-----------------------------------------------+
| FOOTER (size=5) |
| ⌨️ [1-9] Select ❓[H] 🔄[R] 🚪[Q] |
| > user_input_here█ |
+===============================================+
Layout code:
layout = Layout()
layout.split(
Layout(name="header", size=3),
Layout(name="main", ratio=1),
Layout(name="footer", size=5),
)
layout["main"].split(
Layout(name="context", size=6),
Layout(name="content", ratio=1),
)
The TUI uses a custom _read_line() function that
reads input character-by-character in cbreak mode
(tty.setcbreak()) while the fullscreen Live
context remains active. Each keystroke updates the
footer widget's input buffer and triggers a layout
refresh, providing real-time visual feedback without
leaving fullscreen.
Supported key handling:
\x7f, \x08): delete last character\r, \n): submit input\x03): raise KeyboardInterrupt| Location | Emoji | Meaning |
|---|---|---|
| Header bot | 🤖 | Application |
| Conversation | 💬 | Chat / message lines |
| Contact | 👤 | User |
| Context title | 📋 | State / clipboard |
| Current page | 📍 | Location |
| Filled field | ✅ | Done |
| Empty field | ⬜ | Pending |
| Option row | 📋 | Menu item |
| Option gift | 🎁 | Reward / selection |
| Prompt unfilled | ✏️ | Awaiting input |
| Prompt keyboard | ⌨️ | Input device |
| Help | ❓ | Help toggle |
| Restart | 🔄 | Restart |
| Quit | 🚪 | Exit |
| Error | ⚠️ | Warning |
| Goodbye | 👋 | Farewell |
| Waiting | 💭 | Thinking |
chat — Interactive fullscreen TUI# Auto-resolve contact_id from ContactIdSql / Userid in def_conversation
python factory.conversation/ObjConversationTui.py chat CONVERSATION_CODE
# With an explicit contact ID
python factory.conversation/ObjConversationTui.py chat CONVERSATION_CODE CONTACT_ID
When contact_id is omitted, the engine resolves it through the priority
chain: ContactIdSql → Userid field → empty string (new contact).
| Key | Action |
|---|---|
1-9 |
Select a numbered option |
H |
Toggle help overlay |
R |
Restart conversation from page 1 |
L |
Cycle through available languages |
Q |
Quit the TUI |
test — Journey testBFS-traverses all pages reachable from page 1, verifying each page is
reachable and produces output for the user. Prints a Rich table with pass/fail
per page and a summary count.
# Auto-resolve contact_id
python factory.conversation/ObjConversationTui.py test CONVERSATION_CODE
# With an explicit contact ID
python factory.conversation/ObjConversationTui.py test CONVERSATION_CODE CONTACT_ID
Output columns:
| Column | Meaning |
|---|---|
| Page | Page number |
| Reachable | get_pagetext() returned non-empty opts |
| Has Output | Header text is non-empty OR at least one visible option exists |
| Options | Count of visible (non-hidden) options on the page |
| Header (preview) | First 200 characters of the rendered header |
Pages behind dynamic OptionOverrideSql callbacks are discovered when the
override SQL returns rows at test time. Pages reachable only when the SQL
returns no data (e.g. empty date ranges) will not appear in the traversal and
are expected gaps, not failures.
User and client names sourced from the database (typically ALL-CAPS) are
displayed in title case throughout the TUI. The underlying contact_id value
is never modified — only the rendered display strings are converted.
rich -- Already in resource.config/requirements.txttyper -- CLI framework (project standard)termios, tty -- Standard library (Linux terminal control)| Module | Relationship |
|---|---|
factory.conversation/ObjConversationEngine.py |
Base interface class |
factory.conversation/ObjConversationConsole.py |
Reference Console implementation |
factory.core/ObjConversation.py |
Conversation engine that drives the flow |
factory.tui/tui.py |
Reference fullscreen Layout + Live pattern |
factory.core/ObjTUI.py |
Reference TUI_Manager with Live context |
cythonize -3 -a -i ObjConversationTui.py
Compiling factory.conversation/ObjConversationTui.py
Updated : 2026-03-07