{% extends "base.html" %} {% from "_macros.html" import icon, mark %} {% block title %}{{ chat.title if chat else "Chats" }} - LLeMbas{% endblock %} {% block head %} {% endblock %} {% block body_attrs %} data-authenticated="true"{% endblock %} {% block body %}
{% include "partials/sidebar.html" %}
{% if chat %}

{{ chat.title }}

{% if models and can.get("chat.model_select") %}
{% elif current_model %} {{ current_model.label }} {% endif %} {% else %}

Chats

{% endif %}
{% if chat and (can.get("chat.system_prompt") or can.get("chat.params")) %} {# Collapsed by default: these are per-chat overrides, not everyday controls. Each field saves on change rather than needing a Save button, so there is no half-applied state to reason about. #} {% endif %} {% if not chat %} {# No chat selected. #}
{{ mark(cls="empty__mark", uid="empty") }}

The road goes ever on

Pick a chat from the side, or start a new one.

{% elif not models %} {# Nothing to talk to yet. This is the state every fresh install lands in, so it points straight at the fix rather than just reporting a problem. #}
{{ icon("server", "empty__mark") }}

No models available

{% if user.is_admin %} Add an OpenAI-compatible connection and LLeMbas will load its models. {% else %} No model connections have been set up yet. Ask an administrator. {% endif %}

{% if user.is_admin %} {{ icon("server", "icon--sm") }} Set up a connection {% endif %}
{% else %}
{% if not messages %}
{{ mark(cls="empty__mark", uid="intro") }}

What would you ask?

Speak, friend, and enter.

{% endif %} {% for message in messages %} {# Markdown was rendered server-side in pages.py, keyed by message id, so this loop stays a lookup rather than a render. #} {% with body_html = bodies.get(message.id, "") %} {% include "chat/_message.html" %} {% endwith %} {% endfor %}
{% if can.get("files.upload") %} {# Uploads go up as soon as a file is chosen, so the chip (and any rejection) appears immediately rather than at send time. The chips carry hidden inputs, which is how the ids reach the message POST. #}
{% endif %}
{# The chips live outside this form, so their hidden inputs are pulled in explicitly at submit time. #} {% if can.get("files.upload") %} {% endif %}

Enter to send, Shift+Enter for a new line. {% if can.get("files.upload") %} Drag files in, or paste an image. {% if current_model and not current_model.capabilities_json.get("vision") %} {{ current_model.label }} has no vision, so images will not be sent — documents still will. {% endif %} {% endif %}

{% if can.get("files.upload") %} {% endif %}
{% endif %}
{% endblock %}