<!doctype html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Eval Explorer</title> <style> :root { /* Light theme (default) */ --bg-color: #ffffff; --text-color: #333333; --header-bg: #f8f8f8; --border-color: #eaeaea; --code-bg: #f5f5f5; --link-color: #0066cc; --button-bg: #f5f5f5; --button-border: #ddd; --button-active-bg: #0066cc; --button-active-color: white; --button-active-border: #0055aa; --preview-bg: #f5f5f5; --table-line: #f0f0f0; } /* Dark theme */ [data-theme="dark"] { --bg-color: #1e1e1e; --text-color: #e0e0e0; --header-bg: #2d2d2d; --border-color: #444444; --code-bg: #2a2a2a; --link-color: #4da6ff; --button-bg: #333333; --button-border: #555555; --button-active-bg: #0066cc; --button-active-color: white; --button-active-border: #0055aa; --preview-bg: #2a2a2a; --table-line: #333333; } /* Apply theme variables */ body { font-family: monospace; line-height: 1.6; margin: 0; padding: 20px; color: var(--text-color); max-width: 1200px; margin: 0 auto; background-color: var(--bg-color); } h1 { margin-bottom: 20px; border-bottom: 1px solid var(--border-color); padding-bottom: 10px; font-family: monospace; } table { width: 100%; border-collapse: collapse; margin-bottom: 20px; table-layout: fixed; /* Ensure fixed width columns */ } th, td { padding: 10px; text-align: left; border-bottom: 1px dotted var(--border-color); vertical-align: top; word-wrap: break-word; /* Ensure long content wraps */ overflow-wrap: break-word; } th { background-color: var(--header-bg); font-weight: 600; } .collapsible { cursor: pointer; color: var(--link-color); text-decoration: underline; } .hidden { display: none; } .tool-name { font-weight: bold; } .tool-params { padding-left: 20px; color: #666; } pre { background-color: var(--code-bg); padding: 10px; border-radius: 5px; overflow-x: auto; max-height: 200px; margin: 10px 0; font-family: monospace; width: 100%; box-sizing: border-box; white-space: pre-wrap; /* Ensure text wraps */ color: var(--text-color); } code { font-family: monospace; } /* Column sizing */ .turn-column { width: 3%; max-width: 3%; } .text-column { width: 22%; max-width: 22%; } .tool-column { width: 38%; max-width: 38%; } .result-column { width: 37%; max-width: 37%; overflow-x: auto; } /* Content formatting */ .text-content { font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 0.7rem; } .action-container .action-preview, .action-container .action-full { margin-bottom: 5px; } .preview-content { white-space: pre-wrap; margin-bottom: 5px; background-color: var(--preview-bg); padding: 10px; border-radius: 5px; font-family: monospace; width: 100%; box-sizing: border-box; overflow-wrap: break-word; color: var(--text-color); } .show-more { color: var(--link-color); cursor: pointer; text-decoration: none; display: block; margin-top: 5px; } .more-inline { color: var(--link-color); cursor: pointer; text-decoration: none; display: inline; margin-left: 5px; } /* Compact mode styles */ .compact-mode td { padding: 5px; /* Reduced padding in compact mode */ } .compact-mode .preview-content { padding: 2px; margin-bottom: 2px; } .compact-mode pre { padding: 5px; margin: 5px 0; white-space: pre; /* Don't wrap code in compact mode */ overflow-x: auto; /* Add horizontal scrollbar */ } .compact-mode .result-column pre, .compact-mode .result-column .preview-content { max-width: 100%; overflow-x: auto; white-space: pre; } /* Make action containers more compact */ .compact-mode .action-container { margin-bottom: 2px; } /* Reduce space between turns */ .compact-mode tr { border-bottom: 1px solid var(--table-line); } /* Tool params more compact */ .compact-mode .tool-params { padding-left: 10px; margin-top: 2px; } hr { margin: 10px 0; border: 0; height: 1px; background-color: var(--border-color); } /* View switcher */ .view-switcher { display: flex; gap: 10px; margin-bottom: 20px; align-items: center; } .view-button { background-color: var(--button-bg); border: 1px solid var(--button-border); border-radius: 4px; padding: 5px 15px; cursor: pointer; font-family: monospace; font-size: 0.9rem; transition: all 0.2s ease; color: var(--text-color); } .view-button:hover { background-color: var(--button-border); } .view-button.active { background-color: var(--button-active-bg); color: var(--button-active-color); border-color: var(--button-active-border); } /* Navigation bar styles */ .thread-navigation { display: flex; align-items: center; margin-bottom: 20px; padding: 10px 0; border-bottom: 1px solid var(--border-color); } .nav-button { background-color: var(--button-bg); border: 1px solid var(--button-border); border-radius: 4px; padding: 5px 15px; cursor: pointer; font-family: monospace; font-size: 0.9rem; transition: all 0.2s ease; color: var(--text-color); } .nav-button:hover:not(:disabled) { background-color: var(--button-border); } .nav-button:disabled { opacity: 0.5; cursor: not-allowed; } .thread-indicator { margin: 0 15px; font-size: 1rem; flex-grow: 1; text-align: center; } #thread-id { font-weight: bold; } /* Theme switcher */ .theme-switcher { margin-left: auto; display: flex; align-items: center; } .theme-button { background-color: var(--button-bg); border: 1px solid var(--button-border); border-radius: 4px; padding: 5px 10px; cursor: pointer; font-size: 0.9rem; transition: all 0.2s ease; color: var(--text-color); display: flex; align-items: center; } .theme-button:hover { background-color: var(--button-border); } .theme-icon { margin-right: 5px; font-size: 1rem; } </style> </head> <body> <h1 id="current-filename">Thread Explorer</h1> <div class="view-switcher"> <button id="full-view" class="view-button active" onclick="switchView('full')">Full View</button> <button id="compact-view" class="view-button" onclick="switchView('compact')">Compact View</button> <button id="export-button" class="view-button" onclick="exportThreadAsJson()" title="Export current thread as JSON" > Export </button> <div class="theme-switcher"> <button id="theme-toggle" class="theme-button" onclick="toggleTheme()"> <span id="theme-icon" class="theme-icon">☀️</span> <span id="theme-text">Light</span> </button> </div> </div> <div class="thread-navigation"> <button id="prev-thread" class="nav-button" onclick="previousThread()" title="Previous thread (Ctrl+←, k, or h)" disabled > ← Previous </button> <div class="thread-indicator"> Thread <span id="current-thread-index">1</span> of <span id="total-threads">1</span>: <span id="thread-id">Default Thread</span> </div> <button id="next-thread" class="nav-button" onclick="nextThread()" title="Next thread (Ctrl+→, j, or l)" disabled > Next → </button> </div> <table id="thread-table"> <thead> <tr> <th class="turn-column">Turn</th> <th class="text-column">Text</th> <th class="tool-column">Tool</th> <th class="result-column">Result</th> </tr> </thead> <tbody id="thread-body"> <!-- Content will be filled dynamically --> </tbody> </table> <script> // View mode - 'full' or 'compact' let viewMode = "full"; // Theme mode - 'light', 'dark', or 'system' let themeMode = localStorage.getItem("theme") || "system"; // Function to apply theme function applyTheme(theme) { const themeIcon = document.getElementById("theme-icon"); const themeText = document.getElementById("theme-text"); if (theme === "dark") { document.documentElement.setAttribute("data-theme", "dark"); themeIcon.textContent = "🌙"; themeText.textContent = "Dark"; } else { document.documentElement.removeAttribute("data-theme"); themeIcon.textContent = "☀️"; themeText.textContent = "Light"; } } // Function to toggle between light and dark themes function toggleTheme() { // If currently system or light, switch to dark if (themeMode === "system") { const systemDark = window.matchMedia("(prefers-color-scheme: dark)").matches; themeMode = systemDark ? "light" : "dark"; } else { themeMode = themeMode === "light" ? "dark" : "light"; } // Save preference localStorage.setItem("theme", themeMode); // Apply theme applyTheme(themeMode); } // Initialize theme based on system or saved preference function initTheme() { if (themeMode === "system") { // Use system preference const systemDark = window.matchMedia("(prefers-color-scheme: dark)").matches; applyTheme(systemDark ? "dark" : "light"); // Listen for system theme changes window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (e) => { if (themeMode === "system") { applyTheme(e.matches ? "dark" : "light"); } }); } else { // Use saved preference applyTheme(themeMode); } } // Function to switch between view modes function switchView(mode) { viewMode = mode; // Update button states document.getElementById("full-view").classList.toggle("active", mode === "full"); document.getElementById("compact-view").classList.toggle("active", mode === "compact"); // Add or remove compact-mode class on the body document.body.classList.toggle("compact-mode", mode === "compact"); // Re-render the thread with the new view mode renderThread(); } // Function to export the current thread as a JSON file function exportThreadAsJson() { // Clone the thread to avoid modifying the original const threadToExport = JSON.parse(JSON.stringify(thread)); // Create a Blob with the JSON data const blob = new Blob([JSON.stringify(threadToExport, null, 2)], { type: "application/json" }); // Create a download link const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; // Generate filename based on thread ID or index const filename = threadToExport.thread_id || threadToExport.filename || `thread-${currentThreadIndex + 1}.json`; a.download = filename.endsWith(".json") ? filename : `${filename}.json`; // Trigger the download document.body.appendChild(a); a.click(); // Clean up setTimeout(() => { document.body.removeChild(a); URL.revokeObjectURL(url); }, 0); } // Default dummy thread data for preview purposes let dummyThread = { messages: [ { role: "system", content: [{ Text: "System prompt..." }], }, { role: "user", content: [{ Text: "Fix the bug: kwargs not passed..." }], }, { role: "assistant", content: [ { Text: "I'll help you fix that bug." }, { ToolUse: {Lines 1–500 of 949. Load more
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Eval Explorer</title> <style> :root { /* Light theme (default) */ --bg-color: #ffffff; --text-color: #333333; --header-bg: #f8f8f8; --border-color: #eaeaea; --code-bg: #f5f5f5; --link-color: #0066cc; --button-bg: #f5f5f5; --button-border: #ddd; --button-active-bg: #0066cc; --button-active-color: white; --button-active-border: #0055aa; --preview-bg: #f5f5f5; --table-line: #f0f0f0; } /* Dark theme */ [data-theme="dark"] { --bg-color: #1e1e1e; --text-color: #e0e0e0; --header-bg: #2d2d2d; --border-color: #444444; --code-bg: #2a2a2a; --link-color: #4da6ff; --button-bg: #333333; --button-border: #555555; --button-active-bg: #0066cc; --button-active-color: white; --button-active-border: #0055aa; --preview-bg: #2a2a2a; --table-line: #333333; } /* Apply theme variables */ body { font-family: monospace; line-height: 1.6; margin: 0; padding: 20px; color: var(--text-color); max-width: 1200px; margin: 0 auto; background-color: var(--bg-color); } h1 { margin-bottom: 20px; border-bottom: 1px solid var(--border-color); padding-bottom: 10px; font-family: monospace; } table { width: 100%; border-collapse: collapse; margin-bottom: 20px; table-layout: fixed; /* Ensure fixed width columns */ } th, td { padding: 10px; text-align: left; border-bottom: 1px dotted var(--border-color); vertical-align: top; word-wrap: break-word; /* Ensure long content wraps */ overflow-wrap: break-word; } th { background-color: var(--header-bg); font-weight: 600; } .collapsible { cursor: pointer; color: var(--link-color); text-decoration: underline; } .hidden { display: none; } .tool-name { font-weight: bold; } .tool-params { padding-left: 20px; color: #666; } pre { background-color: var(--code-bg); padding: 10px; border-radius: 5px; overflow-x: auto; max-height: 200px; margin: 10px 0; font-family: monospace; width: 100%; box-sizing: border-box; white-space: pre-wrap; /* Ensure text wraps */ color: var(--text-color); } code { font-family: monospace; } /* Column sizing */ .turn-column { width: 3%; max-width: 3%; } .text-column { width: 22%; max-width: 22%; } .tool-column { width: 38%; max-width: 38%; } .result-column { width: 37%; max-width: 37%; overflow-x: auto; } /* Content formatting */ .text-content { font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 0.7rem; } .action-container .action-preview, .action-container .action-full { margin-bottom: 5px; } .preview-content { white-space: pre-wrap; margin-bottom: 5px; background-color: var(--preview-bg); padding: 10px; border-radius: 5px; font-family: monospace; width: 100%; box-sizing: border-box; overflow-wrap: break-word; color: var(--text-color); } .show-more { color: var(--link-color); cursor: pointer; text-decoration: none; display: block; margin-top: 5px; } .more-inline { color: var(--link-color); cursor: pointer; text-decoration: none; display: inline; margin-left: 5px; } /* Compact mode styles */ .compact-mode td { padding: 5px; /* Reduced padding in compact mode */ } .compact-mode .preview-content { padding: 2px; margin-bottom: 2px; } .compact-mode pre { padding: 5px; margin: 5px 0; white-space: pre; /* Don't wrap code in compact mode */ overflow-x: auto; /* Add horizontal scrollbar */ } .compact-mode .result-column pre, .compact-mode .result-column .preview-content { max-width: 100%; overflow-x: auto; white-space: pre; } /* Make action containers more compact */ .compact-mode .action-container { margin-bottom: 2px; } /* Reduce space between turns */ .compact-mode tr { border-bottom: 1px solid var(--table-line); } /* Tool params more compact */ .compact-mode .tool-params { padding-left: 10px; margin-top: 2px; } hr { margin: 10px 0; border: 0; height: 1px; background-color: var(--border-color); } /* View switcher */ .view-switcher { display: flex; gap: 10px; margin-bottom: 20px; align-items: center; } .view-button { background-color: var(--button-bg); border: 1px solid var(--button-border); border-radius: 4px; padding: 5px 15px; cursor: pointer; font-family: monospace; font-size: 0.9rem; transition: all 0.2s ease; color: var(--text-color); } .view-button:hover { background-color: var(--button-border); } .view-button.active { background-color: var(--button-active-bg); color: var(--button-active-color); border-color: var(--button-active-border); } /* Navigation bar styles */ .thread-navigation { display: flex; align-items: center; margin-bottom: 20px; padding: 10px 0; border-bottom: 1px solid var(--border-color); } .nav-button { background-color: var(--button-bg); border: 1px solid var(--button-border); border-radius: 4px; padding: 5px 15px; cursor: pointer; font-family: monospace; font-size: 0.9rem; transition: all 0.2s ease; color: var(--text-color); } .nav-button:hover:not(:disabled) { background-color: var(--button-border); } .nav-button:disabled { opacity: 0.5; cursor: not-allowed; } .thread-indicator { margin: 0 15px; font-size: 1rem; flex-grow: 1; text-align: center; } #thread-id { font-weight: bold; } /* Theme switcher */ .theme-switcher { margin-left: auto; display: flex; align-items: center; } .theme-button { background-color: var(--button-bg); border: 1px solid var(--button-border); border-radius: 4px; padding: 5px 10px; cursor: pointer; font-size: 0.9rem; transition: all 0.2s ease; color: var(--text-color); display: flex; align-items: center; } .theme-button:hover { background-color: var(--button-border); } .theme-icon { margin-right: 5px; font-size: 1rem; } </style> </head> <body> <h1 id="current-filename">Thread Explorer</h1> <div class="view-switcher"> <button id="full-view" class="view-button active" onclick="switchView('full')">Full View</button> <button id="compact-view" class="view-button" onclick="switchView('compact')">Compact View</button> <button id="export-button" class="view-button" onclick="exportThreadAsJson()" title="Export current thread as JSON" > Export </button> <div class="theme-switcher"> <button id="theme-toggle" class="theme-button" onclick="toggleTheme()"> <span id="theme-icon" class="theme-icon">☀️</span> <span id="theme-text">Light</span> </button> </div> </div> <div class="thread-navigation"> <button id="prev-thread" class="nav-button" onclick="previousThread()" title="Previous thread (Ctrl+←, k, or h)" disabled > ← Previous </button> <div class="thread-indicator"> Thread <span id="current-thread-index">1</span> of <span id="total-threads">1</span>: <span id="thread-id">Default Thread</span> </div> <button id="next-thread" class="nav-button" onclick="nextThread()" title="Next thread (Ctrl+→, j, or l)" disabled > Next → </button> </div> <table id="thread-table"> <thead> <tr> <th class="turn-column">Turn</th> <th class="text-column">Text</th> <th class="tool-column">Tool</th> <th class="result-column">Result</th> </tr> </thead> <tbody id="thread-body"> <!-- Content will be filled dynamically --> </tbody> </table> <script> // View mode - 'full' or 'compact' let viewMode = "full"; // Theme mode - 'light', 'dark', or 'system' let themeMode = localStorage.getItem("theme") || "system"; // Function to apply theme function applyTheme(theme) { const themeIcon = document.getElementById("theme-icon"); const themeText = document.getElementById("theme-text"); if (theme === "dark") { document.documentElement.setAttribute("data-theme", "dark"); themeIcon.textContent = "🌙"; themeText.textContent = "Dark"; } else { document.documentElement.removeAttribute("data-theme"); themeIcon.textContent = "☀️"; themeText.textContent = "Light"; } } // Function to toggle between light and dark themes function toggleTheme() { // If currently system or light, switch to dark if (themeMode === "system") { const systemDark = window.matchMedia("(prefers-color-scheme: dark)").matches; themeMode = systemDark ? "light" : "dark"; } else { themeMode = themeMode === "light" ? "dark" : "light"; } // Save preference localStorage.setItem("theme", themeMode); // Apply theme applyTheme(themeMode); } // Initialize theme based on system or saved preference function initTheme() { if (themeMode === "system") { // Use system preference const systemDark = window.matchMedia("(prefers-color-scheme: dark)").matches; applyTheme(systemDark ? "dark" : "light"); // Listen for system theme changes window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (e) => { if (themeMode === "system") { applyTheme(e.matches ? "dark" : "light"); } }); } else { // Use saved preference applyTheme(themeMode); } } // Function to switch between view modes function switchView(mode) { viewMode = mode; // Update button states document.getElementById("full-view").classList.toggle("active", mode === "full"); document.getElementById("compact-view").classList.toggle("active", mode === "compact"); // Add or remove compact-mode class on the body document.body.classList.toggle("compact-mode", mode === "compact"); // Re-render the thread with the new view mode renderThread(); } // Function to export the current thread as a JSON file function exportThreadAsJson() { // Clone the thread to avoid modifying the original const threadToExport = JSON.parse(JSON.stringify(thread)); // Create a Blob with the JSON data const blob = new Blob([JSON.stringify(threadToExport, null, 2)], { type: "application/json" }); // Create a download link const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; // Generate filename based on thread ID or index const filename = threadToExport.thread_id || threadToExport.filename || `thread-${currentThreadIndex + 1}.json`; a.download = filename.endsWith(".json") ? filename : `${filename}.json`; // Trigger the download document.body.appendChild(a); a.click(); // Clean up setTimeout(() => { document.body.removeChild(a); URL.revokeObjectURL(url); }, 0); } // Default dummy thread data for preview purposes let dummyThread = { messages: [ { role: "system", content: [{ Text: "System prompt..." }], }, { role: "user", content: [{ Text: "Fix the bug: kwargs not passed..." }], }, { role: "assistant", content: [ { Text: "I'll help you fix that bug." }, { ToolUse: {