File size: 6,169 Bytes
7533791
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a5baa63
 
 
 
1f909b5
 
a5baa63
 
 
 
 
 
 
 
 
 
 
 
1f909b5
 
 
 
a5baa63
 
 
 
 
 
 
 
 
7533791
a5baa63
 
7533791
 
 
 
 
 
 
 
 
 
 
 
 
 
a5baa63
 
55969ce
718aa48
a84172d
7dfd62b
a84172d
718aa48
 
 
 
 
 
7dfd62b
718aa48
 
7dfd62b
718aa48
a5baa63
7dfd62b
 
 
 
 
 
 
718aa48
 
 
 
 
 
 
 
7dfd62b
718aa48
 
a84172d
01137a2
 
 
 
 
 
 
 
 
 
 
 
 
 
7dfd62b
 
a036d4c
 
 
659188c
a036d4c
659188c
a036d4c
 
 
 
 
55969ce
 
a036d4c
 
659188c
a036d4c
659188c
a036d4c
55969ce
 
718aa48
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a84172d
718aa48
 
 
01137a2
 
a036d4c
 
 
 
 
 
 
 
7533791
718aa48
a84172d
 
a036d4c
 
 
7dfd62b
a036d4c
a84172d
 
1f909b5
 
 
 
 
 
718aa48
1f909b5
 
 
 
 
 
 
 
 
7533791
718aa48
 
7533791
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
// === Dynamic Model Fetching ===
let MODEL_LIST = [];

async function fetchModelList() {
  try {
    const response = await fetch("/models");
    if (response.ok) {
      MODEL_LIST = await response.json();
      initializeDropdowns();
    } else {
      console.error("Failed to fetch model list");
    }
  } catch (error) {
    console.error("Error fetching models:", error);
  }
}

// === Create Custom Dropdowns Dynamically ===
function createDropdown(dropdownId) {
  const dropdown = document.getElementById(dropdownId);
  const selected = dropdown.querySelector(".selected");
  const options = dropdown.querySelector(".options");
  const modelZone = dropdown.closest(".model-zone");
  const nameDisplay = modelZone.querySelector(".model-name");

  MODEL_LIST.forEach(model => {
    const option = document.createElement("div");
    option.className = "p-2 hover:bg-visual_green rounded cursor-pointer";
    option.textContent = model.name;
    option.dataset.value = model.id;
    options.appendChild(option);

    option.addEventListener("click", (e) => {
      e.stopPropagation();
      selected.textContent = model.name;
      dropdown.dataset.value = model.id;
      if (nameDisplay) {
        nameDisplay.textContent = model.name;
        nameDisplay.classList.remove("hidden");
      }
      options.classList.add("hidden");
    });
  });

  selected.addEventListener("click", (e) => {
    e.stopPropagation();
    options.classList.toggle("hidden");
  });

  options.addEventListener("mouseleave", () => {
    options.classList.add("hidden");
  });

  document.addEventListener("click", (e) => {
    if (!dropdown.contains(e.target)) {
      options.classList.add("hidden");
    }
  });
}

// === Initialize All Dropdowns After Fetch ===
function initializeDropdowns() {
  createDropdown("modelA");
  createDropdown("modelB");
  createDropdown("modelC");
  createDropdown("aggregator");
}

// === Theme, Config and Docs Buttons ===
const themeToggle = document.getElementById("themeToggle");
const toggleConfig = document.getElementById("toggleConfig");
const docsButton = document.getElementById("docsButton");
const configPanel = document.getElementById("configPanel");
const html = document.documentElement;

function setInitialTheme() {
  const savedTheme = localStorage.getItem("theme");
  if (savedTheme === "dark") {
    html.classList.add("dark");
    themeToggle.textContent = "πŸŒ™";
  } else if (savedTheme === "light") {
    html.classList.remove("dark");
    themeToggle.textContent = "β˜€οΈ";
  } else {
    const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
    if (prefersDark) {
      html.classList.add("dark");
      themeToggle.textContent = "πŸŒ™";
    } else {
      html.classList.remove("dark");
      themeToggle.textContent = "β˜€οΈ";
    }
  }
}

setInitialTheme();

themeToggle.addEventListener("click", () => {
  const isDark = html.classList.toggle("dark");
  localStorage.setItem("theme", isDark ? "dark" : "light");
  themeToggle.textContent = isDark ? "πŸŒ™" : "β˜€οΈ";
});

toggleConfig.addEventListener("click", () => {
  if (configPanel.classList.contains("minimal")) {
    configPanel.classList.remove("minimal");
    configPanel.classList.add("expanded");
  } else if (configPanel.classList.contains("expanded")) {
    configPanel.classList.remove("expanded");
    configPanel.classList.add("minimal");
  } else {
    configPanel.classList.add("expanded");
    configPanel.classList.remove("hidden");
  }
});

docsButton.addEventListener("click", () => {
  window.location.href = "/docs";
});

// === Per-model Loader Control ===
function showLoader(id) {
  const loader = document.getElementById(`loader${id}`);
  const modelZone = loader.closest(".model-zone");
  loader.classList.remove("hidden");
  modelZone.classList.add("loading");
  loader.innerHTML = `
    <div class="dot bg-aqua"></div>
    <div class="dot bg-aqua animation-delay-150"></div>
    <div class="dot bg-aqua animation-delay-300"></div>
  `;
}

function hideLoader(id) {
  const loader = document.getElementById(`loader${id}`);
  const modelZone = loader.closest(".model-zone");
  loader.classList.add("hidden");
  modelZone.classList.remove("loading");
  loader.innerHTML = "";
}

// === Chat Handling ===
const chatForm = document.getElementById("chatForm");
const userInput = document.getElementById("userInput");
const chatContainer = document.getElementById("chatContainer");

function appendMessage(role, text) {
  const div = document.createElement("div");
  div.className = `p-3 rounded shadow max-w-2xl ${role === "user" ? "bg-blue text-fg0 self-end" : "bg-green text-fg0 self-start"}`;
  div.innerText = text;
  chatContainer.appendChild(div);
  chatContainer.scrollTop = chatContainer.scrollHeight;
}

chatForm.addEventListener("submit", async (e) => {
  e.preventDefault();
  const prompt = userInput.value.trim();
  if (!prompt) return;

  appendMessage("user", prompt);
  userInput.value = "";

  configPanel.classList.remove("expanded");
  configPanel.classList.add("minimal");

  const selections = {
    "LLM-A": document.getElementById("modelA").dataset.value,
    "LLM-B": document.getElementById("modelB").dataset.value,
    "LLM-C": document.getElementById("modelC").dataset.value,
    "LLM-D": document.getElementById("aggregator").dataset.value
  };

  ["A", "B", "C"].forEach(id => showLoader(id));

  const settings = {
    models: {
      "LLM-A": selections["LLM-A"],
      "LLM-B": selections["LLM-B"],
      "LLM-C": selections["LLM-C"]
    },
    aggregator: selections["LLM-D"]
  };

  try {
    const response = await fetch("/chat", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ prompt, settings })
    });

    if (response.ok) {
      const data = await response.json();
      appendMessage("bot", data.response);
    } else {
      appendMessage("bot", "An error occurred. Please check your model selections.");
    }
  } catch (error) {
    appendMessage("bot", "An unexpected error occurred.");
  } finally {
    ["A", "B", "C", "D"].forEach(id => hideLoader(id));
  }
});

// === Kickstart ===
fetchModelList();