diff --git a/static/css/chat.css b/static/css/chat.css index dcca39c..d91e250 100644 --- a/static/css/chat.css +++ b/static/css/chat.css @@ -1011,6 +1011,7 @@ body.loading #version, #scrolling, #import, #export, +#dump, #clear, #upload, #add, @@ -1170,6 +1171,7 @@ label[for="reasoning-tokens"] { #scrolling, #import, #export, +#dump, #clear { position: unset !important; } @@ -1210,6 +1212,15 @@ label[for="reasoning-tokens"] { background-image: url(icons/export.svg); } +#dump { + background-image: url(icons/dump.svg); +} + +#dump.loading { + animation: rotating 1.2s linear infinite; + background-image: url(icons/spinner.svg); +} + #clear { background-image: url(icons/trash.svg); } diff --git a/static/css/icons/dump.svg b/static/css/icons/dump.svg new file mode 100644 index 0000000..dec3380 --- /dev/null +++ b/static/css/icons/dump.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/static/index.html b/static/index.html index ee43108..84d4f37 100644 --- a/static/index.html +++ b/static/index.html @@ -99,6 +99,7 @@
+
diff --git a/static/js/chat.js b/static/js/chat.js index 44fe6c3..152dc9d 100644 --- a/static/js/chat.js +++ b/static/js/chat.js @@ -37,6 +37,7 @@ $scrolling = document.getElementById("scrolling"), $export = document.getElementById("export"), $import = document.getElementById("import"), + $dump = document.getElementById("dump"), $clear = document.getElementById("clear"), $authentication = document.getElementById("authentication"), $authError = document.getElementById("auth-error"), @@ -72,6 +73,7 @@ isResizing = false, scrollResize = false, isUploading = false, + isDumping = false, totalCost = 0; function updateTotalCost() { @@ -1085,15 +1087,7 @@ return true; } - function generate(cancel = false, noPush = false) { - if (abortNow() && cancel) { - return; - } - - if (autoScrolling) { - setFollowTail(true); - } - + function buildRequest(noPush = false) { let temperature = parseFloat($temperature.value); if (Number.isNaN(temperature) || temperature < 0 || temperature > 2) { @@ -1127,11 +1121,7 @@ pushMessage(); } - const controller = new AbortController(); - - $chat.classList.add("completing"); - - const body = { + return { prompt: $prompt.value, model: $model.value, temperature: temperature, @@ -1150,6 +1140,22 @@ }, messages: messages.map(message => message.getData()).filter(Boolean), }; + } + + function generate(cancel = false, noPush = false) { + if (abortNow() && cancel) { + return; + } + + if (autoScrolling) { + setFollowTail(true); + } + + const body = buildRequest(noPush); + + const controller = new AbortController(); + + $chat.classList.add("completing"); let message, generationID, stopTimeout; @@ -1995,6 +2001,42 @@ restore(); }); + $dump.addEventListener("click", async () => { + if (isDumping) { + return; + } + + isDumping = true; + + $dump.classList.add("loading"); + + const body = buildRequest(true); + + try { + const response = await fetch("/-/dump", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(body), + }); + + const json = await response.json(); + + if (!response.ok) { + throw new Error(json?.error || response.statusText); + } + + download("request.json", "application/json", JSON.stringify(json.request, null, 4)); + } catch (err) { + notify(err); + } + + $dump.classList.remove("loading"); + + isDumping = false; + }); + $scrolling.addEventListener("click", () => { autoScrolling = !autoScrolling;