Files
enkly-ai/services/gateway/web/templates/message.html
enkly 79ce8dc4c0
Some checks failed
Go CI Pipeline / build_and_test (push) Failing after 22m0s
Init Project
2026-10-30 18:06:55 +01:00

117 lines
4.7 KiB
HTML

{{/*
Renders a single historical message row. Used for full-page loads.
Tool messages get a collapsible <details> card (native HTML — no JS
needed) instead of a plain bubble, since a run_bash_command or
search_codebase result can be long and isn't usually what you want
to read first when scrolling a past conversation.
*/}}
{{ define "message" }}
{{ if eq .Role "tool" }}
<div class="message-row role-tool">
<details class="tool-card{{ if eq .ToolName "dispatch_subagent" }} is-subagent{{ end }}">
<summary>
<span class="tool-icon tool-icon-{{ .ToolName }}"></span>
<span class="tool-name">{{ .ToolName }}</span>
<span class="tool-chevron" aria-hidden="true"></span>
</summary>
<div class="tool-body">{{ .RenderedHTML }}</div>
</details>
</div>
{{ else if eq .Role "user" }}
<div class="message-row role-user">
<div class="message-content">
<div class="bubble">{{ .RenderedHTML }}</div>
</div>
</div>
{{ else }}
<div class="message-row role-assistant">
<span class="avatar avatar-assistant" aria-hidden="true">
<svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6 21c1.2-2.5 1.5-5.5 1.3-8.5-.5-1.2-1.2-2.4-2.1-3.5C3.5 9 2 7.8 2 6.2 2 4.6 3.5 3.5 5.2 3.5c.8 0 1.5.3 2.1.8C8.5 3 10.1 2.2 12 2.2c1.9 0 3.5.8 4.7 2.1.6-.5 1.3-.8 2.1-.8 1.7 0 3.2 1.1 3.2 2.7 0 1.6-1.5 2.8-3.2 2.8-.9 1.1-1.6 2.3-2.1 3.5-.2 3 .1 6 1.3 8.5H6Zm4-12c.5 1.8 1.2 3.5 2 3.5s1.5-1.7 2-3.5h-4Z"/>
</svg>
</span>
<div class="message-content">
<div class="message-meta"><span class="meta-name">enkly</span></div>
<div class="bubble">{{ .RenderedHTML }}</div>
</div>
</div>
{{ end }}
{{ end }}
{{/*
Renders a tool-call card (used for live streaming and by tests). Data:
ToolName, Summary, Body (already-escaped HTML), IsError.
*/}}
{{ define "tool_call" }}
<div class="message-row role-tool">
<details class="tool-card{{ if .IsError }} is-error{{ end }}{{ if eq .ToolName "dispatch_subagent" }} is-subagent{{ end }}">
<summary>
<span class="tool-icon tool-icon-{{ .ToolName }}"></span>
<span class="tool-name">{{ .ToolName }}</span>
<span class="tool-summary">{{ .Summary }}</span>
<span class="tool-chevron" aria-hidden="true"></span>
</summary>
<div class="tool-body">{{ .Body }}</div>
</details>
</div>
{{ end }}
{{/*
The SSE "tool" payload. htmx applies an out-of-band swap by moving the
CONTENT of the hx-swap-oob element (for any strategy other than
outerHTML), so the target-carrying wrapper is a bare <div> and the real
.message-row lives inside it. "beforebegin" on the assistant row puts
each card above the still-streaming bubble, in execution order.
Data: StreamID plus the tool_call fields.
*/}}
{{ define "tool_call_oob" }}
<div hx-swap-oob="beforebegin:#assistant-row-{{ .StreamID }}">
{{ template "tool_call" . }}
</div>
{{ end }}
{{/*
A single round's standalone reasoning trace, rendered as its own
collapsible card — the per-step counterpart to the single
auto-collapsing "thinking-card" in chat_response.html's
assistant_stream, which only ever shows one running cumulative blob.
This one instead gives each round its own card, inserted above the
assistant bubble in execution order via the same "beforebegin"
OOB-swap trick tool_call_oob uses — so a card for round 0's reasoning
lands right before the tool card it led to, then round 1's reasoning
card lands before round 1's tool card, and so on: discrete,
positioned reasoning steps rather than one blob for the whole turn,
the same interleaved-thinking shape Claude's own UI gives a
tool-using turn. Reuses .tool-card's chrome (border, summary, chevron)
with a thinking-specific icon and a round number, rather than
introducing a parallel set of card styles for what is structurally
the same kind of row. Data: Round (int), Thinking (plain text).
*/}}
{{ define "thinking_round" }}
<div class="message-row role-tool">
<details class="tool-card is-thinking-round">
<summary>
<span class="thinking-icon" aria-hidden="true"></span>
<span class="tool-name">Thinking</span>
<span class="tool-summary">round {{ .Round }}</span>
<span class="tool-chevron" aria-hidden="true"></span>
</summary>
<div class="tool-body"><p class="tool-output">{{ .Thinking }}</p></div>
</details>
</div>
{{ end }}
{{/* The SSE "thinking_round" payload — same OOB wrapper as tool_call_oob. */}}
{{ define "thinking_round_oob" }}
<div hx-swap-oob="beforebegin:#assistant-row-{{ .StreamID }}">
{{ template "thinking_round" . }}
</div>
{{ end }}
{{/* Inline error row returned by POST /chat for validation problems. */}}
{{ define "chat_error" }}
<div class="message-row role-system">
<div class="bubble bubble-error">{{ .Message }}</div>
</div>
{{ end }}