|
46 | 46 | {%- endif %} |
47 | 47 | {% endmacro %} |
48 | 48 |
|
49 | | -{# Todo list #} |
50 | | -{% macro todo_list(todos, tool_id) %} |
51 | | -<div class="todo-list" data-tool-id="{{ tool_id }}"><div class="todo-header"><span class="todo-header-icon">☰</span> Task List</div><ul class="todo-items"> |
| 49 | +{# Todo list - input_json_html is pre-rendered JSON so needs |safe #} |
| 50 | +{% macro todo_list(todos, input_json_html, tool_id) %} |
| 51 | +<div class="todo-list" data-tool-id="{{ tool_id }}"> |
| 52 | +<div class="todo-header"><span class="todo-header-icon">☰</span> Task List |
| 53 | +<div class="view-toggle" role="tablist"> |
| 54 | +<button class="view-toggle-tab active" role="tab" data-view="markdown">Markdown</button> |
| 55 | +<button class="view-toggle-tab" role="tab" data-view="json">JSON</button> |
| 56 | +</div> |
| 57 | +</div> |
| 58 | +<div class="view-markdown"> |
| 59 | +<ul class="todo-items"> |
52 | 60 | {%- for todo in todos -%} |
53 | 61 | {%- set status = todo.status|default('pending') -%} |
54 | 62 | {%- set content = todo.content|default('') -%} |
|
64 | 72 | {%- endif -%} |
65 | 73 | <li class="todo-item {{ status_class }}"><span class="todo-icon">{{ icon }}</span><span class="todo-content">{{ content }}</span></li> |
66 | 74 | {%- endfor -%} |
67 | | -</ul></div> |
| 75 | +</ul> |
| 76 | +</div> |
| 77 | +<div class="view-json"> |
| 78 | +{{ input_json_html|safe }} |
| 79 | +</div> |
| 80 | +</div> |
68 | 81 | {%- endmacro %} |
69 | 82 |
|
70 | | -{# Write tool - content is pre-highlighted so needs |safe #} |
71 | | -{% macro write_tool(file_path, content, tool_id) %} |
| 83 | +{# Write tool - content is pre-highlighted so needs |safe, input_json_html is pre-rendered JSON so needs |safe #} |
| 84 | +{% macro write_tool(file_path, content, input_json_html, tool_id) %} |
72 | 85 | {%- set filename = file_path.split('/')[-1] if '/' in file_path else file_path -%} |
73 | 86 | <div class="file-tool write-tool" data-tool-id="{{ tool_id }}"> |
74 | | -<div class="file-tool-header write-header"><span class="file-tool-icon">📝</span> Write <span class="file-tool-path">{{ filename }}</span></div> |
| 87 | +<div class="file-tool-header write-header"><span class="file-tool-icon">📝</span> Write <span class="file-tool-path">{{ filename }}</span> |
| 88 | +<div class="view-toggle" role="tablist"> |
| 89 | +<button class="view-toggle-tab active" role="tab" data-view="markdown">Markdown</button> |
| 90 | +<button class="view-toggle-tab" role="tab" data-view="json">JSON</button> |
| 91 | +</div> |
| 92 | +</div> |
| 93 | +<div class="view-markdown"> |
75 | 94 | <div class="file-tool-fullpath">{{ file_path }}</div> |
76 | 95 | <div class="truncatable"><div class="truncatable-content"><pre class="file-content highlight">{{ content|safe }}</pre></div><button class="expand-btn">Show more</button></div> |
77 | 96 | </div> |
| 97 | +<div class="view-json"> |
| 98 | +{{ input_json_html|safe }} |
| 99 | +</div> |
| 100 | +</div> |
78 | 101 | {%- endmacro %} |
79 | 102 |
|
80 | | -{# Edit tool - old/new strings are pre-highlighted so need |safe #} |
81 | | -{% macro edit_tool(file_path, old_string, new_string, replace_all, tool_id) %} |
| 103 | +{# Edit tool - old/new strings are pre-highlighted so need |safe, input_json_html is pre-rendered JSON so needs |safe #} |
| 104 | +{% macro edit_tool(file_path, old_string, new_string, replace_all, input_json_html, tool_id) %} |
82 | 105 | {%- set filename = file_path.split('/')[-1] if '/' in file_path else file_path -%} |
83 | 106 | <div class="file-tool edit-tool" data-tool-id="{{ tool_id }}"> |
84 | | -<div class="file-tool-header edit-header"><span class="file-tool-icon">✏️</span> Edit <span class="file-tool-path">{{ filename }}</span>{% if replace_all %} <span class="edit-replace-all">(replace all)</span>{% endif %}</div> |
| 107 | +<div class="file-tool-header edit-header"><span class="file-tool-icon">✏️</span> Edit <span class="file-tool-path">{{ filename }}</span>{% if replace_all %} <span class="edit-replace-all">(replace all)</span>{% endif %} |
| 108 | +<div class="view-toggle" role="tablist"> |
| 109 | +<button class="view-toggle-tab active" role="tab" data-view="markdown">Markdown</button> |
| 110 | +<button class="view-toggle-tab" role="tab" data-view="json">JSON</button> |
| 111 | +</div> |
| 112 | +</div> |
| 113 | +<div class="view-markdown"> |
85 | 114 | <div class="file-tool-fullpath">{{ file_path }}</div> |
86 | 115 | <div class="truncatable"><div class="truncatable-content"> |
87 | 116 | <div class="edit-section edit-old"><div class="edit-label">−</div><pre class="edit-content highlight">{{ old_string|safe }}</pre></div> |
88 | 117 | <div class="edit-section edit-new"><div class="edit-label">+</div><pre class="edit-content highlight">{{ new_string|safe }}</pre></div> |
89 | 118 | </div><button class="expand-btn">Show more</button></div> |
90 | 119 | </div> |
| 120 | +<div class="view-json"> |
| 121 | +{{ input_json_html|safe }} |
| 122 | +</div> |
| 123 | +</div> |
91 | 124 | {%- endmacro %} |
92 | 125 |
|
93 | | -{# Bash tool #} |
94 | | -{% macro bash_tool(command, description, tool_id) %} |
| 126 | +{# Bash tool - description_html is pre-rendered markdown so needs |safe, input_json_html is pre-rendered JSON so needs |safe #} |
| 127 | +{% macro bash_tool(command, description_html, input_json_html, tool_id) %} |
95 | 128 | <div class="tool-use bash-tool" data-tool-id="{{ tool_id }}"> |
96 | | -<div class="tool-header"><span class="tool-icon">$</span> Bash</div> |
97 | | -{%- if description %} |
98 | | -<div class="tool-description">{{ description }}</div> |
| 129 | +<div class="tool-header"><span class="tool-call-label"><span class="call-icon">→</span> Call</span><span class="tool-icon">$</span> Bash |
| 130 | +<div class="view-toggle" role="tablist"> |
| 131 | +<button class="view-toggle-tab active" role="tab" data-view="markdown">Markdown</button> |
| 132 | +<button class="view-toggle-tab" role="tab" data-view="json">JSON</button> |
| 133 | +</div> |
| 134 | +</div> |
| 135 | +<div class="view-markdown"> |
| 136 | +{%- if description_html %} |
| 137 | +<div class="tool-description">{{ description_html|safe }}</div> |
99 | 138 | {%- endif -%} |
100 | 139 | <div class="truncatable"><div class="truncatable-content"><pre class="bash-command">{{ command }}</pre></div><button class="expand-btn">Show more</button></div> |
101 | 140 | </div> |
| 141 | +<div class="view-json"> |
| 142 | +{{ input_json_html|safe }} |
| 143 | +</div> |
| 144 | +</div> |
102 | 145 | {%- endmacro %} |
103 | 146 |
|
104 | | -{# Generic tool use - input_json is pre-formatted so needs |safe #} |
105 | | -{% macro tool_use(tool_name, description, input_json, tool_id) %} |
106 | | -<div class="tool-use" data-tool-id="{{ tool_id }}"><div class="tool-header"><span class="tool-icon">⚙</span> {{ tool_name }}</div> |
107 | | -{%- if description -%} |
108 | | -<div class="tool-description">{{ description }}</div> |
| 147 | +{# Generic tool use - description_html, input_markdown_html, input_json_html are pre-rendered so need |safe #} |
| 148 | +{% macro tool_use(tool_name, tool_icon, description_html, input_markdown_html, input_json_html, tool_id) %} |
| 149 | +<div class="tool-use" data-tool-id="{{ tool_id }}"><div class="tool-header"><span class="tool-call-label"><span class="call-icon">→</span> Call</span><span class="tool-icon">{{ tool_icon }}</span> {{ tool_name }}<div class="view-toggle" role="tablist"><button class="view-toggle-tab active" role="tab" aria-selected="true" data-view="markdown">Markdown</button><button class="view-toggle-tab" role="tab" aria-selected="false" data-view="json">JSON</button></div></div> |
| 150 | +{%- if description_html -%} |
| 151 | +<div class="tool-description">{{ description_html|safe }}</div> |
109 | 152 | {%- endif -%} |
110 | | -<div class="truncatable"><div class="truncatable-content"><pre class="json">{{ input_json }}</pre></div><button class="expand-btn">Show more</button></div></div> |
| 153 | +<div class="truncatable"><div class="truncatable-content"><div class="view-markdown tool-input-rendered">{{ input_markdown_html|safe }}</div><div class="view-json tool-input-rendered">{{ input_json_html|safe }}</div></div><button class="expand-btn">Show more</button></div></div> |
111 | 154 | {%- endmacro %} |
112 | 155 |
|
113 | | -{# Tool result - content_html is pre-rendered so needs |safe #} |
114 | | -{% macro tool_result(content_html, is_error) %} |
| 156 | +{# Tool result - content_markdown_html and content_json_html are pre-rendered so need |safe #} |
| 157 | +{% macro tool_result(content_markdown_html, content_json_html, is_error) %} |
115 | 158 | {%- set error_class = ' tool-error' if is_error else '' -%} |
116 | | -<div class="tool-result{{ error_class }}"><div class="truncatable"><div class="truncatable-content">{{ content_html|safe }}</div><button class="expand-btn">Show more</button></div></div> |
| 159 | +<div class="tool-result{{ error_class }}"><div class="tool-result-header"><span class="tool-result-label">{% if is_error %}<span class="result-icon">✗</span> Error{% else %}<span class="result-icon">←</span> Result{% endif %}</span><div class="view-toggle" role="tablist"><button class="view-toggle-tab active" role="tab" aria-selected="true" data-view="markdown">Markdown</button><button class="view-toggle-tab" role="tab" aria-selected="false" data-view="json">JSON</button></div></div><div class="truncatable"><div class="truncatable-content"><div class="view-markdown">{{ content_markdown_html|safe }}</div><div class="view-json">{{ content_json_html|safe }}</div></div><button class="expand-btn">Show more</button></div></div> |
117 | 160 | {%- endmacro %} |
118 | 161 |
|
119 | 162 | {# Tool pair wrapper - tool_use_html/tool_result_html are pre-rendered #} |
120 | 163 | {% macro tool_pair(tool_use_html, tool_result_html) %} |
121 | 164 | <div class="tool-pair">{{ tool_use_html|safe }}{{ tool_result_html|safe }}</div> |
122 | 165 | {%- endmacro %} |
123 | 166 |
|
| 167 | +{# Collapsible cell wrapper for message sections #} |
| 168 | +{% macro cell(cell_type, label, content_html, open_by_default=false, count=0, raw_content="") %} |
| 169 | +<details class="cell {{ cell_type }}-cell"{% if open_by_default %} open{% endif %}> |
| 170 | +<summary class="cell-header"> |
| 171 | +<span class="cell-label">{{ label }}{% if count %} ({{ count }}){% endif %}</span> |
| 172 | +{% if cell_type == 'tools' %} |
| 173 | +<div class="view-toggle cell-view-toggle" role="tablist"> |
| 174 | +<button class="view-toggle-tab active" role="tab" data-view="markdown">All Markdown</button> |
| 175 | +<button class="view-toggle-tab" role="tab" data-view="json">All JSON</button> |
| 176 | +</div> |
| 177 | +{% endif %} |
| 178 | +<button class="cell-copy-btn" aria-label="Copy {{ label }}" tabindex="0"{% if raw_content %} data-copy-content="{{ raw_content | e }}"{% endif %}>Copy</button> |
| 179 | +</summary> |
| 180 | +<div class="cell-content">{{ content_html|safe }}</div> |
| 181 | +</details> |
| 182 | +{%- endmacro %} |
| 183 | + |
124 | 184 | {# Thinking block - content_html is pre-rendered markdown so needs |safe #} |
125 | 185 | {% macro thinking(content_html) %} |
126 | 186 | <div class="thinking"><div class="thinking-label">Thinking</div>{{ content_html|safe }}</div> |
|
151 | 211 | {%- endif %} |
152 | 212 | {%- endmacro %} |
153 | 213 |
|
154 | | -{# Message wrapper - content_html is pre-rendered so needs |safe #} |
155 | | -{% macro message(role_class, role_label, msg_id, timestamp, content_html) %} |
156 | | -<div class="message {{ role_class }}" id="{{ msg_id }}"><div class="message-header"><span class="role-label">{{ role_label }}</span><a href="#{{ msg_id }}" class="timestamp-link"><time datetime="{{ timestamp }}" data-timestamp="{{ timestamp }}">{{ timestamp }}</time></a></div><div class="message-content">{{ content_html|safe }}</div></div> |
| 214 | +{# Message metadata subsection #} |
| 215 | +{% macro metadata(char_count, token_estimate, tool_counts) %} |
| 216 | +<details class="message-metadata"> |
| 217 | +<summary>Metadata</summary> |
| 218 | +<div class="metadata-content"> |
| 219 | +<div class="metadata-item"><span class="metadata-label">Chars:</span><span class="metadata-value">{{ char_count }}</span></div> |
| 220 | +<div class="metadata-item"><span class="metadata-label">Tokens:</span><span class="metadata-value">~{{ token_estimate }}</span></div> |
| 221 | +{%- if tool_counts %} |
| 222 | +{%- for tool_name, count in tool_counts.items() %} |
| 223 | +<div class="metadata-item"><span class="metadata-label">{{ tool_name }}:</span><span class="metadata-value">{{ count }}</span></div> |
| 224 | +{%- endfor %} |
| 225 | +{%- endif %} |
| 226 | +</div> |
| 227 | +</details> |
| 228 | +{%- endmacro %} |
| 229 | + |
| 230 | +{# Message wrapper - content_html is pre-rendered so needs |safe, metadata_html is optional #} |
| 231 | +{% macro message(role_class, role_label, msg_id, timestamp, content_html, metadata_html="") %} |
| 232 | +<div class="message {{ role_class }}" id="{{ msg_id }}"><div class="message-header"><span class="role-label">{{ role_label }}</span><a href="#{{ msg_id }}" class="timestamp-link"><time datetime="{{ timestamp }}" data-timestamp="{{ timestamp }}">{{ timestamp }}</time></a></div>{{ metadata_html|safe }}<div class="message-content">{{ content_html|safe }}</div></div> |
157 | 233 | {%- endmacro %} |
158 | 234 |
|
159 | 235 | {# Continuation wrapper - content_html is pre-rendered so needs |safe #} |
|
0 commit comments