mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-10 05:39:11 +00:00
Reduce promise based nesting in chat JS func used in desktop, web client
Use async/await to reduce .then() based nesting to improve code readability
This commit is contained in:
@@ -346,115 +346,113 @@
|
|||||||
chatInput.classList.remove("option-enabled");
|
chatInput.classList.remove("option-enabled");
|
||||||
|
|
||||||
// Call specified Khoj API which returns a streamed response of type text/plain
|
// Call specified Khoj API which returns a streamed response of type text/plain
|
||||||
fetch(url, { headers })
|
let response = await fetch(url, { headers });
|
||||||
.then(response => {
|
const reader = response.body.getReader();
|
||||||
const reader = response.body.getReader();
|
const decoder = new TextDecoder();
|
||||||
const decoder = new TextDecoder();
|
let rawResponse = "";
|
||||||
let rawResponse = "";
|
let references = null;
|
||||||
let references = null;
|
|
||||||
|
|
||||||
function readStream() {
|
function readStream() {
|
||||||
reader.read().then(({ done, value }) => {
|
reader.read().then(({ done, value }) => {
|
||||||
if (done) {
|
if (done) {
|
||||||
// Append any references after all the data has been streamed
|
// Append any references after all the data has been streamed
|
||||||
if (references != null) {
|
if (references != null) {
|
||||||
newResponseText.appendChild(references);
|
newResponseText.appendChild(references);
|
||||||
}
|
}
|
||||||
document.getElementById("chat-body").scrollTop = document.getElementById("chat-body").scrollHeight;
|
document.getElementById("chat-body").scrollTop = document.getElementById("chat-body").scrollHeight;
|
||||||
document.getElementById("chat-input").removeAttribute("disabled");
|
document.getElementById("chat-input").removeAttribute("disabled");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode message chunk from stream
|
||||||
|
const chunk = decoder.decode(value, { stream: true });
|
||||||
|
|
||||||
|
if (chunk.includes("### compiled references:")) {
|
||||||
|
const additionalResponse = chunk.split("### compiled references:")[0];
|
||||||
|
rawResponse += additionalResponse;
|
||||||
|
newResponseText.innerHTML = "";
|
||||||
|
newResponseText.appendChild(formatHTMLMessage(rawResponse));
|
||||||
|
|
||||||
|
const rawReference = chunk.split("### compiled references:")[1];
|
||||||
|
const rawReferenceAsJson = JSON.parse(rawReference);
|
||||||
|
references = document.createElement('div');
|
||||||
|
references.classList.add("references");
|
||||||
|
|
||||||
|
let referenceExpandButton = document.createElement('button');
|
||||||
|
referenceExpandButton.classList.add("reference-expand-button");
|
||||||
|
|
||||||
|
let referenceSection = document.createElement('div');
|
||||||
|
referenceSection.classList.add("reference-section");
|
||||||
|
referenceSection.classList.add("collapsed");
|
||||||
|
|
||||||
|
let numReferences = 0;
|
||||||
|
|
||||||
|
// If rawReferenceAsJson is a list, then count the length
|
||||||
|
if (Array.isArray(rawReferenceAsJson)) {
|
||||||
|
numReferences = rawReferenceAsJson.length;
|
||||||
|
|
||||||
|
rawReferenceAsJson.forEach((reference, index) => {
|
||||||
|
let polishedReference = generateReference(reference, index);
|
||||||
|
referenceSection.appendChild(polishedReference);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
numReferences += processOnlineReferences(referenceSection, rawReferenceAsJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
references.appendChild(referenceExpandButton);
|
||||||
|
|
||||||
|
referenceExpandButton.addEventListener('click', function() {
|
||||||
|
if (referenceSection.classList.contains("collapsed")) {
|
||||||
|
referenceSection.classList.remove("collapsed");
|
||||||
|
referenceSection.classList.add("expanded");
|
||||||
|
} else {
|
||||||
|
referenceSection.classList.add("collapsed");
|
||||||
|
referenceSection.classList.remove("expanded");
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Decode message chunk from stream
|
let expandButtonText = numReferences == 1 ? "1 reference" : `${numReferences} references`;
|
||||||
const chunk = decoder.decode(value, { stream: true });
|
referenceExpandButton.innerHTML = expandButtonText;
|
||||||
|
references.appendChild(referenceSection);
|
||||||
|
readStream();
|
||||||
|
} else {
|
||||||
|
// Display response from Khoj
|
||||||
|
if (newResponseText.getElementsByClassName("spinner").length > 0) {
|
||||||
|
newResponseText.removeChild(loadingSpinner);
|
||||||
|
}
|
||||||
|
|
||||||
if (chunk.includes("### compiled references:")) {
|
// Try to parse the chunk as a JSON object. It will be a JSON object if there is an error.
|
||||||
const additionalResponse = chunk.split("### compiled references:")[0];
|
if (chunk.startsWith("{") && chunk.endsWith("}")) {
|
||||||
rawResponse += additionalResponse;
|
try {
|
||||||
|
const responseAsJson = JSON.parse(chunk);
|
||||||
|
if (responseAsJson.image) {
|
||||||
|
rawResponse += ``;
|
||||||
|
}
|
||||||
|
if (responseAsJson.detail) {
|
||||||
|
rawResponse += responseAsJson.detail;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// If the chunk is not a JSON object, just display it as is
|
||||||
|
rawResponse += chunk;
|
||||||
|
} finally {
|
||||||
newResponseText.innerHTML = "";
|
newResponseText.innerHTML = "";
|
||||||
newResponseText.appendChild(formatHTMLMessage(rawResponse));
|
newResponseText.appendChild(formatHTMLMessage(rawResponse));
|
||||||
|
|
||||||
const rawReference = chunk.split("### compiled references:")[1];
|
|
||||||
const rawReferenceAsJson = JSON.parse(rawReference);
|
|
||||||
references = document.createElement('div');
|
|
||||||
references.classList.add("references");
|
|
||||||
|
|
||||||
let referenceExpandButton = document.createElement('button');
|
|
||||||
referenceExpandButton.classList.add("reference-expand-button");
|
|
||||||
|
|
||||||
let referenceSection = document.createElement('div');
|
|
||||||
referenceSection.classList.add("reference-section");
|
|
||||||
referenceSection.classList.add("collapsed");
|
|
||||||
|
|
||||||
let numReferences = 0;
|
|
||||||
|
|
||||||
// If rawReferenceAsJson is a list, then count the length
|
|
||||||
if (Array.isArray(rawReferenceAsJson)) {
|
|
||||||
numReferences = rawReferenceAsJson.length;
|
|
||||||
|
|
||||||
rawReferenceAsJson.forEach((reference, index) => {
|
|
||||||
let polishedReference = generateReference(reference, index);
|
|
||||||
referenceSection.appendChild(polishedReference);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
numReferences += processOnlineReferences(referenceSection, rawReferenceAsJson);
|
|
||||||
}
|
|
||||||
|
|
||||||
references.appendChild(referenceExpandButton);
|
|
||||||
|
|
||||||
referenceExpandButton.addEventListener('click', function() {
|
|
||||||
if (referenceSection.classList.contains("collapsed")) {
|
|
||||||
referenceSection.classList.remove("collapsed");
|
|
||||||
referenceSection.classList.add("expanded");
|
|
||||||
} else {
|
|
||||||
referenceSection.classList.add("collapsed");
|
|
||||||
referenceSection.classList.remove("expanded");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let expandButtonText = numReferences == 1 ? "1 reference" : `${numReferences} references`;
|
|
||||||
referenceExpandButton.innerHTML = expandButtonText;
|
|
||||||
references.appendChild(referenceSection);
|
|
||||||
readStream();
|
|
||||||
} else {
|
|
||||||
// Display response from Khoj
|
|
||||||
if (newResponseText.getElementsByClassName("spinner").length > 0) {
|
|
||||||
newResponseText.removeChild(loadingSpinner);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to parse the chunk as a JSON object. It will be a JSON object if there is an error.
|
|
||||||
if (chunk.startsWith("{") && chunk.endsWith("}")) {
|
|
||||||
try {
|
|
||||||
const responseAsJson = JSON.parse(chunk);
|
|
||||||
if (responseAsJson.image) {
|
|
||||||
rawResponse += ``;
|
|
||||||
}
|
|
||||||
if (responseAsJson.detail) {
|
|
||||||
rawResponse += responseAsJson.detail;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
// If the chunk is not a JSON object, just display it as is
|
|
||||||
rawResponse += chunk;
|
|
||||||
} finally {
|
|
||||||
newResponseText.innerHTML = "";
|
|
||||||
newResponseText.appendChild(formatHTMLMessage(rawResponse));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If the chunk is not a JSON object, just display it as is
|
|
||||||
rawResponse += chunk;
|
|
||||||
newResponseText.innerHTML = "";
|
|
||||||
newResponseText.appendChild(formatHTMLMessage(rawResponse));
|
|
||||||
|
|
||||||
readStream();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// If the chunk is not a JSON object, just display it as is
|
||||||
|
rawResponse += chunk;
|
||||||
|
newResponseText.innerHTML = "";
|
||||||
|
newResponseText.appendChild(formatHTMLMessage(rawResponse));
|
||||||
|
|
||||||
// Scroll to bottom of chat window as chat response is streamed
|
readStream();
|
||||||
document.getElementById("chat-body").scrollTop = document.getElementById("chat-body").scrollHeight;
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
readStream();
|
|
||||||
|
// Scroll to bottom of chat window as chat response is streamed
|
||||||
|
document.getElementById("chat-body").scrollTop = document.getElementById("chat-body").scrollHeight;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
readStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
function incrementalChat(event) {
|
function incrementalChat(event) {
|
||||||
|
|||||||
@@ -309,7 +309,7 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
return element
|
return element
|
||||||
}
|
}
|
||||||
|
|
||||||
function chat() {
|
async function chat() {
|
||||||
// Extract required fields for search from form
|
// Extract required fields for search from form
|
||||||
let query = document.getElementById("chat-input").value.trim();
|
let query = document.getElementById("chat-input").value.trim();
|
||||||
let resultsCount = localStorage.getItem("khojResultsCount") || 5;
|
let resultsCount = localStorage.getItem("khojResultsCount") || 5;
|
||||||
@@ -351,115 +351,113 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
chatInput.classList.remove("option-enabled");
|
chatInput.classList.remove("option-enabled");
|
||||||
|
|
||||||
// Call specified Khoj API which returns a streamed response of type text/plain
|
// Call specified Khoj API which returns a streamed response of type text/plain
|
||||||
fetch(url)
|
let response = await fetch(url);
|
||||||
.then(response => {
|
const reader = response.body.getReader();
|
||||||
const reader = response.body.getReader();
|
const decoder = new TextDecoder();
|
||||||
const decoder = new TextDecoder();
|
let rawResponse = "";
|
||||||
let rawResponse = "";
|
let references = null;
|
||||||
let references = null;
|
|
||||||
|
|
||||||
function readStream() {
|
function readStream() {
|
||||||
reader.read().then(({ done, value }) => {
|
reader.read().then(({ done, value }) => {
|
||||||
if (done) {
|
if (done) {
|
||||||
// Append any references after all the data has been streamed
|
// Append any references after all the data has been streamed
|
||||||
if (references != null) {
|
if (references != null) {
|
||||||
newResponseText.appendChild(references);
|
newResponseText.appendChild(references);
|
||||||
}
|
}
|
||||||
document.getElementById("chat-body").scrollTop = document.getElementById("chat-body").scrollHeight;
|
document.getElementById("chat-body").scrollTop = document.getElementById("chat-body").scrollHeight;
|
||||||
document.getElementById("chat-input").removeAttribute("disabled");
|
document.getElementById("chat-input").removeAttribute("disabled");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode message chunk from stream
|
||||||
|
const chunk = decoder.decode(value, { stream: true });
|
||||||
|
|
||||||
|
if (chunk.includes("### compiled references:")) {
|
||||||
|
const additionalResponse = chunk.split("### compiled references:")[0];
|
||||||
|
rawResponse += additionalResponse;
|
||||||
|
newResponseText.innerHTML = "";
|
||||||
|
newResponseText.appendChild(formatHTMLMessage(rawResponse));
|
||||||
|
|
||||||
|
const rawReference = chunk.split("### compiled references:")[1];
|
||||||
|
const rawReferenceAsJson = JSON.parse(rawReference);
|
||||||
|
references = document.createElement('div');
|
||||||
|
references.classList.add("references");
|
||||||
|
|
||||||
|
let referenceExpandButton = document.createElement('button');
|
||||||
|
referenceExpandButton.classList.add("reference-expand-button");
|
||||||
|
|
||||||
|
let referenceSection = document.createElement('div');
|
||||||
|
referenceSection.classList.add("reference-section");
|
||||||
|
referenceSection.classList.add("collapsed");
|
||||||
|
|
||||||
|
let numReferences = 0;
|
||||||
|
|
||||||
|
// If rawReferenceAsJson is a list, then count the length
|
||||||
|
if (Array.isArray(rawReferenceAsJson)) {
|
||||||
|
numReferences = rawReferenceAsJson.length;
|
||||||
|
|
||||||
|
rawReferenceAsJson.forEach((reference, index) => {
|
||||||
|
let polishedReference = generateReference(reference, index);
|
||||||
|
referenceSection.appendChild(polishedReference);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
numReferences += processOnlineReferences(referenceSection, rawReferenceAsJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
references.appendChild(referenceExpandButton);
|
||||||
|
|
||||||
|
referenceExpandButton.addEventListener('click', function() {
|
||||||
|
if (referenceSection.classList.contains("collapsed")) {
|
||||||
|
referenceSection.classList.remove("collapsed");
|
||||||
|
referenceSection.classList.add("expanded");
|
||||||
|
} else {
|
||||||
|
referenceSection.classList.add("collapsed");
|
||||||
|
referenceSection.classList.remove("expanded");
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Decode message chunk from stream
|
let expandButtonText = numReferences == 1 ? "1 reference" : `${numReferences} references`;
|
||||||
const chunk = decoder.decode(value, { stream: true });
|
referenceExpandButton.innerHTML = expandButtonText;
|
||||||
|
references.appendChild(referenceSection);
|
||||||
|
readStream();
|
||||||
|
} else {
|
||||||
|
// Display response from Khoj
|
||||||
|
if (newResponseText.getElementsByClassName("spinner").length > 0) {
|
||||||
|
newResponseText.removeChild(loadingSpinner);
|
||||||
|
}
|
||||||
|
|
||||||
if (chunk.includes("### compiled references:")) {
|
// Try to parse the chunk as a JSON object. It will be a JSON object if there is an error.
|
||||||
const additionalResponse = chunk.split("### compiled references:")[0];
|
if (chunk.startsWith("{") && chunk.endsWith("}")) {
|
||||||
rawResponse += additionalResponse;
|
try {
|
||||||
|
const responseAsJson = JSON.parse(chunk);
|
||||||
|
if (responseAsJson.image) {
|
||||||
|
rawResponse += ``;
|
||||||
|
}
|
||||||
|
if (responseAsJson.detail) {
|
||||||
|
rawResponse += responseAsJson.detail;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// If the chunk is not a JSON object, just display it as is
|
||||||
|
rawResponse += chunk;
|
||||||
|
} finally {
|
||||||
newResponseText.innerHTML = "";
|
newResponseText.innerHTML = "";
|
||||||
newResponseText.appendChild(formatHTMLMessage(rawResponse));
|
newResponseText.appendChild(formatHTMLMessage(rawResponse));
|
||||||
|
|
||||||
const rawReference = chunk.split("### compiled references:")[1];
|
|
||||||
const rawReferenceAsJson = JSON.parse(rawReference);
|
|
||||||
references = document.createElement('div');
|
|
||||||
references.classList.add("references");
|
|
||||||
|
|
||||||
let referenceExpandButton = document.createElement('button');
|
|
||||||
referenceExpandButton.classList.add("reference-expand-button");
|
|
||||||
|
|
||||||
let referenceSection = document.createElement('div');
|
|
||||||
referenceSection.classList.add("reference-section");
|
|
||||||
referenceSection.classList.add("collapsed");
|
|
||||||
|
|
||||||
let numReferences = 0;
|
|
||||||
|
|
||||||
// If rawReferenceAsJson is a list, then count the length
|
|
||||||
if (Array.isArray(rawReferenceAsJson)) {
|
|
||||||
numReferences = rawReferenceAsJson.length;
|
|
||||||
|
|
||||||
rawReferenceAsJson.forEach((reference, index) => {
|
|
||||||
let polishedReference = generateReference(reference, index);
|
|
||||||
referenceSection.appendChild(polishedReference);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
numReferences += processOnlineReferences(referenceSection, rawReferenceAsJson);
|
|
||||||
}
|
|
||||||
|
|
||||||
references.appendChild(referenceExpandButton);
|
|
||||||
|
|
||||||
referenceExpandButton.addEventListener('click', function() {
|
|
||||||
if (referenceSection.classList.contains("collapsed")) {
|
|
||||||
referenceSection.classList.remove("collapsed");
|
|
||||||
referenceSection.classList.add("expanded");
|
|
||||||
} else {
|
|
||||||
referenceSection.classList.add("collapsed");
|
|
||||||
referenceSection.classList.remove("expanded");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let expandButtonText = numReferences == 1 ? "1 reference" : `${numReferences} references`;
|
|
||||||
referenceExpandButton.innerHTML = expandButtonText;
|
|
||||||
references.appendChild(referenceSection);
|
|
||||||
readStream();
|
|
||||||
} else {
|
|
||||||
// Display response from Khoj
|
|
||||||
if (newResponseText.getElementsByClassName("spinner").length > 0) {
|
|
||||||
newResponseText.removeChild(loadingSpinner);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to parse the chunk as a JSON object. It will be a JSON object if there is an error.
|
|
||||||
if (chunk.startsWith("{") && chunk.endsWith("}")) {
|
|
||||||
try {
|
|
||||||
const responseAsJson = JSON.parse(chunk);
|
|
||||||
if (responseAsJson.image) {
|
|
||||||
rawResponse += ``;
|
|
||||||
}
|
|
||||||
if (responseAsJson.detail) {
|
|
||||||
rawResponse += responseAsJson.detail;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
// If the chunk is not a JSON object, just display it as is
|
|
||||||
rawResponse += chunk;
|
|
||||||
} finally {
|
|
||||||
newResponseText.innerHTML = "";
|
|
||||||
newResponseText.appendChild(formatHTMLMessage(rawResponse));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If the chunk is not a JSON object, just display it as is
|
|
||||||
rawResponse += chunk;
|
|
||||||
newResponseText.innerHTML = "";
|
|
||||||
newResponseText.appendChild(formatHTMLMessage(rawResponse));
|
|
||||||
readStream();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
// Scroll to bottom of chat window as chat response is streamed
|
// If the chunk is not a JSON object, just display it as is
|
||||||
document.getElementById("chat-body").scrollTop = document.getElementById("chat-body").scrollHeight;
|
rawResponse += chunk;
|
||||||
});
|
newResponseText.innerHTML = "";
|
||||||
|
newResponseText.appendChild(formatHTMLMessage(rawResponse));
|
||||||
|
readStream();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
readStream();
|
|
||||||
|
// Scroll to bottom of chat window as chat response is streamed
|
||||||
|
document.getElementById("chat-body").scrollTop = document.getElementById("chat-body").scrollHeight;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
readStream();
|
||||||
|
};
|
||||||
|
|
||||||
function incrementalChat(event) {
|
function incrementalChat(event) {
|
||||||
if (!event.shiftKey && event.key === 'Enter') {
|
if (!event.shiftKey && event.key === 'Enter') {
|
||||||
|
|||||||
Reference in New Issue
Block a user