bifroest/app/templates/_message.html
2026-10-27 08:34:17 +01:00

65 lines
4.5 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<article class="card {{ 'aiw-message-user' if m.role == 'user' else 'aiw-message-assistant' }}" id="message-{{ m.id }}">
<div class="card-body stack stack-sm">
{% set u = m.usage or {} %}
<p class="aiw-meta">
<span class="aiw-meta-who">{{ 'Frage' if m.role == 'user' else 'Antwort' }}</span>
<span>{{ m.created.strftime('%H:%M') }}</span>
{% if m.role == 'assistant' and m.model %}<span class="aiw-pill">{{ m.model }}</span>{% endif %}
{% if m.role == 'assistant' and u.get('context_tokens') and u.get('context_window') %}{% set pct = (100 * u.context_tokens / u.context_window)|round|int %}<span class="aiw-pill{{ ' aiw-pill-danger' if pct >= 80 }}" title="Geschätzte Größe der Anfrage im Verhältnis zum Kontextfenster des Modells">Kontext {{ pct }} %</span>{% endif %}
{% if m.role == 'assistant' and u.get('rules') %}<span class="aiw-pill" title="Projektregeln aus dem Repository, die die KI befolgt hat">Regeln: {{ u.rules|join(', ') }}</span>{% endif %}
{% if m.role == 'assistant' and u.get('hugin') %}<span class="aiw-pill" title="Pakete aus Hugin, die für diese Antwort galten">Hugin: {% for k, v in u.hugin.items() %}{{ k }} {{ v }}{{ ', ' if not loop.last }}{% endfor %}</span>{% endif %}
{% if m.role == 'user' and u.get('command') %}<span class="aiw-pill" title="Slash-Befehl aus Hugin; an die KI ging der ausgeschriebene Text">Befehl {{ u.command.id }} {{ u.command.version }}</span>{% endif %}
</p>
{% set calls = m.items|selectattr('type', 'equalto', 'function_call')|list if m.items else [] %}
{% if calls %}
<details class="text-sm">
<summary class="text-muted">{{ calls|length }} Tool-Aufruf{{ 'e' if calls|length != 1 }}</summary>
<ol class="aiw-tools">{% for c in calls %}<li><code>{{ c.name }}</code> <span class="text-muted aiw-break">{{ c.arguments }}</span></li>{% endfor %}</ol>
</details>
{% endif %}
{% if m.role == 'assistant' %}
<div class="aiw-markdown" data-copy-source>{{ m.content|markdown }}</div>
{% for call in (results|default({})).get(m.run_id, []) %}
{% set r = call.result %}
{% set figure = chart(r.columns, r.rows) %}
<details class="aiw-result">
<summary>Abfrageergebnis: {{ r.rows|length }} Zeile{{ 'n' if r.rows|length != 1 }}{% if r.truncated %} (gekürzt){% endif %}, {{ r.columns|length }} Spalte{{ 'n' if r.columns|length != 1 }}{% if figure %} · mit Diagramm{% endif %}</summary>
<div class="stack stack-sm">
{% if call.arguments.get('sql') %}<pre class="text-xs aiw-message">{{ call.arguments.sql }}</pre>{% endif %}
{% if figure %}{{ figure }}{% endif %}
<div class="table-wrap aiw-result-table"><table>
<thead><tr>{% for c in r.columns %}<th>{{ c }}</th>{% endfor %}</tr></thead>
<tbody>{% for row in r.rows %}<tr>{% for v in row %}<td>{{ '–' if v is none else v }}</td>{% endfor %}</tr>{% endfor %}</tbody>
</table></div>
<p class="cluster text-xs"><a class="btn btn-ghost btn-xs" href="/tool-calls/{{ call.id }}.csv" download>Als CSV herunterladen</a>
{% if r.truncated %}<span class="text-muted">Nur die ersten {{ r.rows|length }} Zeilen; für vollständige Auswertungen die KI aggregieren lassen.</span>{% endif %}</p>
</div>
</details>
{% endfor %}
{% if (m.usage or {}).get('round_limit') %}
<div class="alert alert-info" role="status"><div class="alert-content">
<p class="text-sm">Das Limit an Tool-Schritten für eine Antwort ist erreicht; die KI hat den Stand zusammengefasst.</p>
{% if latest %}
<form hx-post="/chats/{{ m.chat_session_id }}/messages" hx-target="#messages" hx-swap="beforeend">
<input type="hidden" name="_csrf" value="{{ p.csrf }}">
<input type="hidden" name="content" value="Bitte mach dort weiter, wo du aufgehört hast.">
<button class="btn btn-primary btn-sm" type="submit">Weiterarbeiten</button>
</form>
{% endif %}
</div></div>
{% endif %}
<div class="aiw-message-actions">
<button class="btn btn-ghost btn-xs" type="button" data-copy>Kopieren</button>
{% with message_id = m.id, fb = (feedback|default({})).get(m.id), thanks = false %}{% include "_feedback.html" %}{% endwith %}
</div>
{% else %}
<div class="aiw-message">{{ m.content }}</div>
{% if (m.usage or {}).get('command') and m.items %}
<details class="text-sm">
<summary class="text-muted">An die KI gesendet</summary>
<div class="aiw-message text-sm">{{ m.items[0].content }}</div>
</details>
{% endif %}
{% endif %}
</div>
</article>