1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2025-10-20 20:12:39 +03:00
Files
bookstack/resources/js/components/query-manager.ts
Dan Brown 8eef5a1ee7 Vectors: Updated query response to use server-side-events
Allowing the vector query results and the LLM response to each come back
over the same HTTP request at two different times via a somewhat
standard.

Uses a package for JS SSE client, since native browser client does not
support over POST, which is probably important for this endpoint as we
don't want crawlers or other bots abusing this via accidentally.
2025-08-21 16:03:55 +01:00

57 lines
1.9 KiB
TypeScript

import {Component} from "./component";
import {createEventSource} from "eventsource-client";
export class QueryManager extends Component {
protected input!: HTMLTextAreaElement;
protected generatedLoading!: HTMLElement;
protected generatedDisplay!: HTMLElement;
protected contentLoading!: HTMLElement;
protected contentDisplay!: HTMLElement;
protected form!: HTMLFormElement;
setup() {
this.input = this.$refs.input as HTMLTextAreaElement;
this.form = this.$refs.form as HTMLFormElement;
this.generatedLoading = this.$refs.generatedLoading;
this.generatedDisplay = this.$refs.generatedDisplay;
this.contentLoading = this.$refs.contentLoading;
this.contentDisplay = this.$refs.contentDisplay;
// TODO - Start lookup if query set
// TODO - Update URL on query change
// TODO - Handle query form submission
this.form.addEventListener('submit', event => {
event.preventDefault();
this.runQuery();
});
}
async runQuery() {
this.contentLoading.hidden = false;
this.generatedLoading.hidden = false;
this.contentDisplay.innerHTML = '';
this.generatedDisplay.innerHTML = '';
const query = this.input.value;
const es = window.$http.eventSource('/query', 'POST', {query});
let messageCount = 0;
for await (const {data, event, id} of es) {
messageCount++;
if (messageCount === 1) {
// Entity results
this.contentDisplay.innerText = data; // TODO - Update to HTML
this.contentLoading.hidden = true;
} else if (messageCount === 2) {
// LLM Output
this.generatedDisplay.innerText = data; // TODO - Update to HTML
this.generatedLoading.hidden = true;
} else {
es.close()
break;
}
}
}
}