blob: b535fa1ac9279c954be5412bbbc3aa86a8034407 [file] [log] [blame]
Sean McCullough86b56862025-04-18 13:04:03 -07001<html>
2 <head>
3 <title>sketch-timeline demo</title>
4 <link rel="stylesheet" href="demo.css" />
Philip Zeyliger72682df2025-04-23 13:09:46 -07005 <script type="module" src="../sketch-timeline.ts"></script>
Sean McCullough86b56862025-04-18 13:04:03 -07006 <script>
7 const messages = [
8 {
Philip Zeyligere31d2a92025-05-11 15:22:35 -07009 type: "agent",
10 end_of_turn: false,
11 content:
12 "Now I'll create an empty commit with a very long commit message:",
13 tool_calls: [
14 {
15 name: "bash",
16 input:
17 '{"command":"git commit --allow-empty -m \\"chore: create empty commit with very long message\\\\n\\\\nThis is an extremely long commit message to demonstrate how Git handles verbose commit messages.\\\\nThis empty commit has no actual code changes, but contains a lengthy explanation.\\\\n\\\\nThe empty commit pattern can be useful in several scenarios:\\\\n1. Triggering CI/CD pipelines without modifying code\\\\n2. Marking significant project milestones or releases\\\\n3. Creating annotated reference points in the commit history\\\\n4. Documenting important project decisions\\\\n\\\\nEmpty commits are created using the --allow-empty flag, which instructs Git to \\\\ncreate a commit even when there are no changes staged for commit. This bypasses\\\\nGit\'s normal behavior of refusing to record a commit that has the exact same\\\\ntree as its parent.\\\\n\\\\nSome technical details about empty commits:\\\\n- They still receive a unique commit hash\\\\n- They appear in the git log like any other commit\\\\n- They can be referenced by other git commands\\\\n- They can be included in merges, rebases, and other git operations\\\\n- They take up minimal space in the repository\\\\n\\\\nThis commit message continues to be extremely verbose just to demonstrate how\\\\nGit handles very long commit messages and how they appear in various Git interfaces.\\\\nThe content of this message is not particularly meaningful but serves to\\\\ndemonstrate the ability to include detailed context when necessary.\\\\n\\\\nMore lines of explanation follow to make this commit message truly excessive...\\\\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ultrices ligula\\\\nnon tellus tincidunt, in volutpat nisi venenatis. Phasellus convallis felis nec\\\\ndiam dignissim, vel fringilla odio ultricies. Morbi feugiat velit in nulla\\\\nconsequat, eget facilisis dui vehicula. Donec fermentum nisl vel justo ultricies,\\\\nut semper libero ultrices. \\\\n\\\\nCras sagittis libero vitae diam eleifend, vel viverra eros tempus.\\\\nSuspendisse potenti. Nullam ac pede. Curabitur blandit hendrerit nibh.\\\\nDonec quis augue ut diam lobortis venenatis. Quisque dapibus justo eget neque.\\\\nInteger sit amet ligula vitae arcu interdum ultrices. Nullam ornare, magna sed\\\\nvenenatis tincidunt, libero urna ullamcorper tortor, ac ultrices neque sem ut massa.\\" --trailer \'Co-Authored-By: sketch <hello@sketch.dev>\' --trailer \'Change-ID: s$(openssl rand -hex 8)k\'"}',
18 tool_call_id: "toolu_01X67pzGzW2NtTjZnxoXTMc7",
19 args: '{"command":"git commit --allow-empty -m \\"chore: create empty commit with very long message\\\\n\\\\nThis is an extremely long commit message to demonstrate how Git handles verbose commit messages..."}',
20 result:
21 "[detached HEAD abc1234] chore: create empty commit with very long message\n 1 file changed, 1 insertion(+), 1 deletion(-)",
22 },
23 ],
24 timestamp: "2025-05-11T21:44:48.760674089Z",
25 conversation_id: "3qc-ptm3",
26 usage: {
27 input_tokens: 6,
28 cache_creation_input_tokens: 77,
29 cache_read_input_tokens: 4230,
30 output_tokens: 668,
31 cost_usd: 0.01159575,
32 },
33 start_time: "2025-05-11T21:44:35.577868468Z",
34 end_time: "2025-05-11T21:44:48.760670506Z",
35 elapsed: 13182802037,
36 idx: 8,
37 },
38 {
Sean McCullough86b56862025-04-18 13:04:03 -070039 type: "user",
40 content: "a user message",
Philip Zeyliger16fa8b42025-05-02 04:28:16 +000041 timestamp: "2025-04-14T16:39:30.639533919Z",
42 conversation_id: "conv-123456",
43 idx: 0,
Sean McCullough86b56862025-04-18 13:04:03 -070044 },
45 {
46 type: "agent",
Philip Zeyliger16fa8b42025-05-02 04:28:16 +000047 content: "an agent message with usage information",
48 timestamp: "2025-04-14T16:39:31.639533919Z",
49 conversation_id: "conv-123456",
50 idx: 1,
51 usage: {
52 input_tokens: 4,
53 cache_creation_input_tokens: 2620,
54 cache_read_input_tokens: 0,
55 output_tokens: 106,
56 cost_usd: 0.011427,
57 },
Sean McCullough86b56862025-04-18 13:04:03 -070058 },
59 {
60 type: "agent",
Philip Zeyliger16fa8b42025-05-02 04:28:16 +000061 content: "an agent message with a single tool call",
62 timestamp: "2025-04-14T16:39:32.639533919Z",
63 conversation_id: "conv-123456",
64 idx: 2,
65 tool_calls: [
66 {
67 name: "bash",
68 input: 'find . -type f -name "*.go" | wc -l',
69 tool_call_id: "call_12345",
70 args: '{"command": "find . -type f -name \\"*.go\\" | wc -l"}',
71 result: "486",
72 },
73 ],
Sean McCullough86b56862025-04-18 13:04:03 -070074 },
75 {
76 type: "agent",
Philip Zeyliger16fa8b42025-05-02 04:28:16 +000077 content:
78 "an agent message with a bash command that is extremely long and would create a horizontal scrollbar",
79 timestamp: "2025-04-14T16:39:32.739533919Z",
80 conversation_id: "conv-123456",
81 idx: 2.5,
82 tool_calls: [
83 {
84 name: "bash",
85 input:
86 'find /app -type f -name "*.ts" -o -name "*.js" -o -name "*.tsx" -o -name "*.jsx" | xargs grep -l "useState" | while read file; do echo "File: $file"; grep -n "useState" $file | head -5; echo; done | head -50',
87 tool_call_id: "call_verylongbash",
88 args: '{"command": "find /app -type f -name \\"*.ts\\" -o -name \\"*.js\\" -o -name \\"*.tsx\\" -o -name \\"*.jsx\\" | xargs grep -l \\"useState\\" | while read file; do echo \\"File: $file\\"; grep -n \\"useState\\" $file | head -5; echo; done | head -50"}',
89 result:
90 'File: /app/webui/src/web-components/sketch-chat-input.ts\n97: useState,\n\nFile: /app/webui/src/web-components/sketch-diff-view.ts\n47:import { createRef, ref, useState } from "lit/directives/ref.js";\n110: const [selectedFiles, setSelectedFiles] = useState([]);\n',
91 },
92 ],
93 },
94 {
95 type: "agent",
96 content:
97 "an agent message with a bash command that has a very long output that would create a horizontal scrollbar",
98 timestamp: "2025-04-14T16:39:32.839533919Z",
99 conversation_id: "conv-123456",
100 idx: 2.7,
101 tool_calls: [
102 {
103 name: "bash",
104 input: "cat /app/webui/package.json | grep -A 5 dependencies",
105 tool_call_id: "call_longoutput",
106 args: '{"command": "cat /app/webui/package.json | grep -A 5 dependencies"}',
107 result:
108 ' "dependencies": {\n "@xterm/addon-fit": "^0.10.0",\n "@xterm/xterm": "^5.5.0",\n "diff2html": "3.4.51",\n "lit": "^3.2.1",\n "marked": "^15.0.7",\n "mermaid": "^11.6.0",\n "sanitize-html": "^2.15.0",\n "vega": "^5.33.0",\n "vega-embed": "^6.29.0",\n "vega-lite": "^5.23.0",\n "react": "^18.2.0",\n "react-dom": "^18.2.0",\n "styled-components": "^6.1.8",\n "tailwindcss": "^3.4.1",\n "typescript": "^5.3.3",\n "zod": "^3.22.4",\n "@types/react": "^18.2.55",\n "@types/react-dom": "^18.2.19",\n "eslint": "^8.56.0",\n "prettier": "^3.2.5"\n },',
109 },
110 ],
111 },
112 {
113 type: "agent",
114 content:
115 "an agent message with two tool calls that will show how the width behaves with very long content that should push the boundaries of the UI layout with really wide tool calls that might stretch beyond the regular message content width",
116 timestamp: "2025-04-14T16:39:33.639533919Z",
117 conversation_id: "conv-123456",
118 idx: 3,
119 tool_calls: [
120 {
121 name: "keyword_search",
122 input: "Search for files related to the timeline component",
123 tool_call_id: "call_67890",
124 args: '{"query": "Find all files related to the timeline component in the project", "search_terms": ["timeline", "message", "component", "web-components"]}',
125 result:
126 "Found 3 files: sketch-timeline.ts, sketch-timeline-message.ts, sketch-timeline.demo.html",
127 },
128 {
129 name: "patch",
130 input: "Update the timeline component CSS",
131 tool_call_id: "call_abcdef",
132 args: '{"path": "/app/webui/src/web-components/sketch-timeline.ts", "patches": [{"operation": "replace", "oldText": "width: 100%;", "newText": "width: auto; max-width: 100%;"}, {"operation": "replace", "oldText": "margin-bottom: 20px;", "newText": "margin-bottom: 24px;"}]}',
133 result: "Applied all patches successfully",
134 },
135 ],
Sean McCullough86b56862025-04-18 13:04:03 -0700136 },
137 {
138 type: "user",
Philip Zeyliger16fa8b42025-05-02 04:28:16 +0000139 content: "another user message",
140 timestamp: "2025-04-14T16:39:34.639533919Z",
141 conversation_id: "conv-123456",
142 idx: 4,
Sean McCullough86b56862025-04-18 13:04:03 -0700143 },
Sean McCullough2c5bba42025-04-20 19:33:17 -0700144 {
145 type: "agent",
Philip Zeyliger16fa8b42025-05-02 04:28:16 +0000146 content: "an agent message with detailed information and usage data",
147 timestamp: "2025-04-14T16:39:35.639533919Z",
148 conversation_id: "conv-123456",
149 idx: 5,
150 usage: {
151 input_tokens: 125,
152 cache_creation_input_tokens: 0,
153 cache_read_input_tokens: 3050,
154 output_tokens: 245,
155 cost_usd: 0.023456,
156 },
Sean McCullough2c5bba42025-04-20 19:33:17 -0700157 },
158 {
159 type: "tool",
160 content: "a tool use message",
Philip Zeyliger16fa8b42025-05-02 04:28:16 +0000161 timestamp: "2025-04-14T16:39:36.639533919Z",
162 conversation_id: "conv-123456",
163 idx: 6,
Sean McCullough2c5bba42025-04-20 19:33:17 -0700164 },
165 {
166 type: "commit",
167 end_of_turn: false,
168 content: "",
169 commits: [
170 {
171 hash: "ece101c103ec231da87f4df05c1b5e6a24e13add",
172 subject: "Add README.md for web components directory",
Philip Zeyliger2032b1c2025-04-23 19:40:42 -0700173 body: "This adds documentation for the web components used in the Loop UI,\nincluding a description of each component, usage examples, and\ndevelopment guidelines.\n\nCo-Authored-By: sketch\nadd README.md for webui/src/web-components",
Sean McCullough2c5bba42025-04-20 19:33:17 -0700174 pushed_branch:
175 "sketch/create-readmemd-for-web-components-directory",
176 },
177 ],
Philip Zeyliger16fa8b42025-05-02 04:28:16 +0000178 timestamp: "2025-04-14T16:39:37.639533919Z",
179 conversation_id: "conv-123456",
180 idx: 7,
Sean McCullough2c5bba42025-04-20 19:33:17 -0700181 },
182 {
183 type: "agent",
184 content: "an end-of-turn agent message",
185 end_of_turn: true,
Philip Zeyliger16fa8b42025-05-02 04:28:16 +0000186 timestamp: "2025-04-14T16:39:38.639533919Z",
187 conversation_id: "conv-123456",
188 idx: 8,
189 usage: {
190 input_tokens: 85,
191 cache_creation_input_tokens: 1240,
192 cache_read_input_tokens: 750,
193 output_tokens: 178,
194 cost_usd: 0.018976,
195 },
Sean McCullough2c5bba42025-04-20 19:33:17 -0700196 },
Sean McCullough86b56862025-04-18 13:04:03 -0700197 ];
Sean McCullough2c5bba42025-04-20 19:33:17 -0700198
Sean McCullough86b56862025-04-18 13:04:03 -0700199 document.addEventListener("DOMContentLoaded", () => {
Sean McCullough2c5bba42025-04-20 19:33:17 -0700200 const appShell = document.querySelector(".app-shell");
Sean McCullough71941bd2025-04-18 13:31:48 -0700201 const timelineEl = document.querySelector("sketch-timeline");
Sean McCullough86b56862025-04-18 13:04:03 -0700202 timelineEl.messages = messages;
Sean McCullough2c5bba42025-04-20 19:33:17 -0700203 timelineEl.scrollContainer = appShell;
204 const addMessagesCheckbox = document.querySelector("#addMessages");
205 addMessagesCheckbox.addEventListener("change", toggleAddMessages);
206
207 let addingMessages = false;
208 const addNewMessagesInterval = 1000;
209
210 function addNewMessages() {
211 if (!addingMessages) {
212 return;
213 }
214 const n = new Date().getMilliseconds() % messages.length;
215 const msgToDup = messages[n];
216 const dup = JSON.parse(JSON.stringify(msgToDup));
217 dup.idx = messages.length;
218 dup.timestamp = new Date().toISOString();
219 messages.push(dup);
220 timelineEl.messages = messages.concat();
221 timelineEl.prop;
222 timelineEl.requestUpdate();
223 }
224
225 let addMessagesHandler = setInterval(
226 addNewMessages,
227 addNewMessagesInterval,
228 );
229
230 function toggleAddMessages() {
231 addingMessages = !addingMessages;
232 if (addingMessages) {
233 } else {
234 }
235 }
Sean McCullough86b56862025-04-18 13:04:03 -0700236 });
237 </script>
Sean McCullough2c5bba42025-04-20 19:33:17 -0700238 <style>
Philip Zeyligere31d2a92025-05-11 15:22:35 -0700239 /* Fix for bash command overflow */
240 sketch-timeline-message::part(message-content),
241 sketch-tool-calls::part(tool-call-card),
242 sketch-tool-card::part(summary) {
243 max-width: 100% !important;
244 overflow: hidden !important;
245 text-overflow: ellipsis !important;
246 white-space: nowrap !important;
247 }
248
Sean McCullough2c5bba42025-04-20 19:33:17 -0700249 .app-shell {
250 display: block;
251 font-family:
252 system-ui,
253 -apple-system,
254 BlinkMacSystemFont,
255 "Segoe UI",
256 Roboto,
257 sans-serif;
258 color: rgb(51, 51, 51);
259 line-height: 1.4;
260 min-height: 100vh;
261 width: 100%;
262 position: relative;
263 overflow-x: hidden;
264 }
265 .app-header {
266 flex-grow: 0;
267 }
268 .view-container {
269 flex-grow: 2;
270 }
271 </style>
Sean McCullough86b56862025-04-18 13:04:03 -0700272 </head>
273 <body>
Sean McCullough2c5bba42025-04-20 19:33:17 -0700274 <div class="app-shell">
275 <div class="app-header">
276 <h1>sketch-timeline demo</h1>
277 <input
278 type="checkbox"
279 id="addMessages"
280 title="Automatically add new messages"
281 /><label for="addMessages">Automatically add new messages</label>
282 </div>
283 <div class="view-container">
284 <div class="chat-view view-active">
285 <sketch-timeline></sketch-timeline>
286 </div>
287 </div>
288 </div>
Sean McCullough86b56862025-04-18 13:04:03 -0700289 </body>
Sean McCullough71941bd2025-04-18 13:31:48 -0700290</html>