fileViewer.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. let currentFileName = null; // Store the current file name
  2. let trajectoryDirectory = ""; // Global variable to store the directory
  3. let timeoutIds = []; // Store timeout IDs for pending operations
  4. function getBaseUrl() {
  5. const protocol = window.location.protocol;
  6. const host = window.location.hostname;
  7. const port = window.location.port;
  8. // Use the default port if the port number is empty (for standard HTTP/HTTPS)
  9. const defaultPort =
  10. protocol === "http:" && !port
  11. ? "80"
  12. : protocol === "https:" && !port
  13. ? "443"
  14. : port;
  15. return `${protocol}//${host}:${defaultPort}`;
  16. }
  17. function fetchFiles() {
  18. const baseUrl = getBaseUrl();
  19. fetch(`${baseUrl}/files`)
  20. .then((response) => response.json())
  21. .then((files) => {
  22. const fileList = document.getElementById("fileList");
  23. fileList.innerHTML = "";
  24. files.forEach((file) => {
  25. const fileElement = document.createElement("li");
  26. fileElement.textContent = file;
  27. fileElement.onclick = () => viewFile(file.split(" ")[0]);
  28. fileList.appendChild(fileElement);
  29. });
  30. });
  31. }
  32. // translate item.role to what we show the user
  33. const roleMap = {
  34. user: "Environment",
  35. assistant: "SWE-Agent",
  36. subroutine: "SWE-Agent subroutine",
  37. default: "Default",
  38. system: "System",
  39. demo: "Demonstration",
  40. };
  41. function getRoleText(role) {
  42. return roleMap[role] || role;
  43. }
  44. function viewFile(fileName) {
  45. // Clear any pending message loading from previous files
  46. timeoutIds.forEach((timeoutId) => clearTimeout(timeoutId));
  47. timeoutIds = []; // Reset the list of timeout IDs
  48. const baseUrl = getBaseUrl();
  49. fetch(`${baseUrl}/trajectory/${fileName}`)
  50. .then((response) => {
  51. if (!response.ok) {
  52. throw new Error("Network response was not ok");
  53. }
  54. return response.json();
  55. })
  56. .then((content) => {
  57. const container = document.getElementById("fileContent");
  58. container.innerHTML = ""; // Clear existing content
  59. if (content.history && Array.isArray(content.history)) {
  60. let delay = 200; // Initial delay
  61. const delayIncrement = 50; // Delay between each message, in milliseconds
  62. content.history.forEach((item, index) => {
  63. const timeoutId = setTimeout(() => {
  64. const contentText = item.content
  65. ? item.content.replace(/</g, "&lt;").replace(/>/g, "&gt;")
  66. : "";
  67. let roleClass =
  68. item.agent && item.agent !== "primary"
  69. ? "subroutine"
  70. : item.role
  71. ? item.role.toLowerCase().replaceAll(" ", "-")
  72. : "default";
  73. const elementId = "historyItem" + index;
  74. const historyItem = document.createElement("div");
  75. historyItem.className = `history-item ${roleClass} fade-in`;
  76. historyItem.id = elementId;
  77. if (contentText.includes("--- DEMONSTRATION ---")) {
  78. item.role = "demo";
  79. } else if ("is_demo" in item && item.is_demo === true) {
  80. item.role += "[demo]";
  81. }
  82. historyItem.innerHTML = `
  83. <div class="role-bar ${roleClass}">
  84. <strong>
  85. <span>${getRoleText(item.role)}</span>
  86. </strong>
  87. </div>
  88. <div class="content-container">
  89. <pre>${contentText}</pre>
  90. </div>
  91. <div class="shadow"></div>
  92. `;
  93. container.appendChild(historyItem);
  94. }, delay);
  95. delay += delayIncrement; // Increment delay for the next message
  96. timeoutIds.push(timeoutId); // Store the timeout ID
  97. });
  98. } else {
  99. container.textContent = "No history content found.";
  100. }
  101. })
  102. .catch((error) => {
  103. console.error("Error fetching file:", error);
  104. document.getElementById("fileContent").textContent =
  105. "Error loading content. " + error;
  106. });
  107. // Highlight the selected file in the list
  108. document.querySelectorAll("#fileList li").forEach((li) => {
  109. li.classList.remove("selected");
  110. if (li.textContent.split(" ")[0] === fileName) {
  111. li.classList.add("selected");
  112. }
  113. });
  114. }
  115. function refreshCurrentFile() {
  116. if (currentFileName) {
  117. const currentScrollPosition =
  118. document.documentElement.scrollTop || document.body.scrollTop;
  119. viewFile(currentFileName.split(" ")[0]); // Reload the current file
  120. // Restore the scroll position after the content is loaded
  121. setTimeout(() => {
  122. window.scrollTo(0, currentScrollPosition);
  123. }, 100);
  124. }
  125. }
  126. function fetchDirectoryInfo() {
  127. const baseUrl = getBaseUrl();
  128. fetch(`${baseUrl}/directory_info`)
  129. .then((response) => response.json())
  130. .then((data) => {
  131. if (data.directory) {
  132. trajectoryDirectory = data.directory; // Store the directory
  133. document.title = `Trajectory Viewer: ${data.directory}`;
  134. document.querySelector("h1").textContent =
  135. `Trajectory Viewer: ${data.directory}`;
  136. }
  137. })
  138. .catch((error) => console.error("Error fetching directory info:", error));
  139. }
  140. window.onload = function () {
  141. fetchFiles();
  142. fetchDirectoryInfo();
  143. };