117 lines
4.7 KiB
HTML
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 }}
|