UI — NiceGUI

NiceGUI entry point for Klea web interfaces.

This file is invoked directly to start the NiceGUI web interface. It reads title / subtitle / server URL from sys.argv and delegates to klea_utils.ui.web.nicegui.runner.run_nicegui_app().

Usage:

python app.py <title> <subtitle> <server_url> [--debug]

File: klea_utils/ui/web/nicegui/app.py

Copyright 2026 Ankur Sinha Author: Ankur Sinha <sanjay DOT ankur AT gmail DOT com>

NiceGUI runner for Klea web interfaces.

This module implements the main UI logic for the NiceGUI web interface, including the 3-column layout, chat functionality, and inspector panel.

File: klea_utils/ui/web/nicegui/runner.py

Copyright 2026 Ankur Sinha Author: Ankur Sinha <sanjay DOT ankur AT gmail DOT com>

klea_utils.ui.web.nicegui.runner.run_nicegui_app(title: str, server_url: str, subtitle: str = '', disclaimer: str = '', footer_text: str = 'Powered by <a href="https://github.com/neuroml/klea">Klea</a>', debug: bool = False, nicegui_url: str = '0.0.0.0:7860', storage_secret: str = 'klea-nicegui-secret-change-me', app_name: str = 'klea-web') None[source]

Start the NiceGUI web server with the Klea chat interface.

This function is the main entry point for the NiceGUI frontend. It registers a @ui.page("/") handler that builds the full UI via setup_layout() and then starts the NiceGUI server.

Parameters:
  • title – Application title (displayed in the header and browser tab).

  • server_url – Base URL of the backend API server (e.g. http://127.0.0.1:8005).

  • subtitle – Optional smaller text shown next to title in the header.

  • disclaimer – Optional text shown below the chat input.

  • footer_text – HTML content for the footer bar.

  • debug – When True, enable NiceGUI’s file-watch hot reload (reload=True). Set to False in production.

  • nicegui_urlhost:port to bind the NiceGUI web server to (default: "0.0.0.0:7860").

  • storage_secret – Secret used by NiceGUI for browser session persistence (default: "klea-nicegui-secret-change-me").

  • app_name – Log identity for this frontend process, used as the log file name so each app keeps its own logs (e.g. "klea-rag-web").

klea_utils.ui.web.nicegui.runner.setup_layout(chat_id: str, server_url: str, user_id: str = '', title: str = 'Klea', subtitle: str = '', disclaimer: str = '', footer_text: str = 'Powered by <a href="https://github.com/neuroml/klea">Klea</a>') None[source]

Build the full page UI: header, drawers, chat area, and footer.

User messages appear as right-aligned bubbles (grey background); system / bot messages are left-aligned, full-width and transparent, matching the Gemini/ChatGPT model without avatars.

Layout (left to right):

[left_drawer | center_column | right_drawer]

The left drawer uses Quasar’s mini mode to provide a ChatGPT-style rail that shows only icons when collapsed and full text when expanded.

Parameters:
  • chat_id – Chat conversation identifier.

  • server_url – Base URL of the backend API server.

  • user_id – Opaque persistent user identifier.

  • title – Bold application title in the header bar.

  • subtitle – Optional smaller text shown next to title in the header.

  • disclaimer – Optional text shown below the chat input.

  • footer_text – HTML content for the footer bar.

Reusable custom NiceGUI widgets for Klea web interfaces.

File: klea_utils/ui/web/nicegui/widgets.py

Copyright 2026 Ankur Sinha Author: Ankur Sinha <sanjay DOT ankur AT gmail DOT com>

class klea_utils.ui.web.nicegui.widgets.ChatBubble(text: str, stamp: str, is_user: bool, collapsed: bool, idx: int, on_expand=None, on_copy=None)[source]

Bases: Element

A custom chat message bubble with built-in actions.

Replaces ui.chat_message with full control over the layout. Each bubble has collapsible text content, a timestamp, a copy button, and an expand / collapse toggle – all flowing naturally inside the bubble (no CSS hacks).

Usage inside a @ui.refreshable:

ChatBubble(
    text="Hello", stamp="12:00", is_user=True,
    collapsed=False, idx=0,
    on_expand=lambda: print("toggle"),
    on_copy=lambda: print("copy"),
)

Server API client for the NiceGUI frontend.

All functions accept the server_url as their first argument so the caller can point them at any running Klea backend without shared state.

File: klea_utils/ui/web/nicegui/client.py

Copyright 2026 Ankur Sinha Author: Ankur Sinha <sanjay DOT ankur AT gmail DOT com>

async klea_utils.ui.web.nicegui.client.clear_model_override(server_url: str, user_id: str, chat_id: str, role: str) bool[source]

DELETE the model override for a chat role.

async klea_utils.ui.web.nicegui.client.create_chat_on_server(server_url: str, user_id: str, chat_id: str) None[source]

POST a new chat to the server so it persists.

async klea_utils.ui.web.nicegui.client.delete_chat_on_server(server_url: str, user_id: str, chat_id: str) None[source]

DELETE the chat on the server.

async klea_utils.ui.web.nicegui.client.hydrate_chats(server_url: str, user_id: str) None[source]

Fetch all chats and their messages from the server into the local state.

Populates the in-memory chats dict with every conversation belonging to user_id, including the full message history for each chat.

After this call the frontend can switch between any chat without additional server round-trips. If the server has no data for this user yet the local store stays empty.

async klea_utils.ui.web.nicegui.client.rename_chat_on_server(server_url: str, user_id: str, chat_id: str, title: str) None[source]

PATCH the chat title on the server.

async klea_utils.ui.web.nicegui.client.set_model_override(server_url: str, user_id: str, chat_id: str, role: str, payload: dict) bool[source]

POST a model override for a chat role.

In-memory chat state for the NiceGUI frontend.

Keyed by {user_id}:{chat_id} so that colliding chat_ids across different users do not interfere.

File: klea_utils/ui/web/nicegui/state.py

Copyright 2026 Ankur Sinha Author: Ankur Sinha <sanjay DOT ankur AT gmail DOT com>

klea_utils.ui.web.nicegui.state.ensure_chat(user_id: str, chat_id: str) dict[source]

Return the chat session dict for user_id / chat_id, creating it if missing.

Each chat session dict has the following keys:

name                Human-readable display name (auto-generated)
created             ``datetime.timestamp()`` of creation (float).
pinned              Whether the chat session is pinned to the top of the list.
messages            List of ``(text, stamp, is_user)`` tuples where
                    *is_user* is ``True`` for user messages and
                    ``False`` for bot / system messages.
inspector_entries   List of dicts with info/debug events for the most
                    recent query in this chat session.
inspector_expanded  Set of indices into *inspector_entries* that are
                    currently expanded in the UI.
state_sections      Dict of ``{node_label: section_data}`` for the status
                    pane, ordered by first insertion (per node label).
model_info          Dict of active model config per role
                    (from ``fetch_active_models``).
token_usage         Numeric token totals accumulated for this in-memory
                    chat session.
klea_utils.ui.web.nicegui.state.get_chats_sorted(user_id: str) list[tuple[str, dict]][source]

Return (chat_id, data) pairs for user_id, pinned first, then by creation desc.

Filters by the user_id prefix so that in a multi-browser scenario (same NiceGUI process) each user only sees their own chats.

Argparse parser for the Klea NiceGUI frontend entry point.

Provides a standard argparse parser for the arguments passed by the Typer web command when it launches app.py. The entry point simply calls make_parser().parse_args() and picks only the arguments it needs.

Usage:

from klea_utils.ui.web.nicegui.parser import make_parser

args = make_parser("My frontend").parse_args()
run_app(
    args.title, args.url,
    subtitle=args.subtitle,
    disclaimer=args.disclaimer,
    debug=args.debug,
)

File: klea_utils/ui/web/nicegui/parser.py

Copyright 2026 Ankur Sinha Author: Ankur Sinha <sanjay DOT ankur AT gmail DOT com>

klea_utils.ui.web.nicegui.parser.make_parser(description: str = 'Klea web interface') ArgumentParser[source]

Return a preconfigured argparse.ArgumentParser.

Parameters:

description – Description shown in --help.