send and display the conversation name
This commit is contained in:
parent
43017bca36
commit
e45fde5178
4 changed files with 62 additions and 4 deletions
|
@ -1,3 +1,5 @@
|
||||||
|
import { Signal } from "@char/aftercare";
|
||||||
|
|
||||||
const main = document.querySelector("main")!;
|
const main = document.querySelector("main")!;
|
||||||
|
|
||||||
async function nav() {
|
async function nav() {
|
||||||
|
@ -9,7 +11,7 @@ async function nav() {
|
||||||
button.addEventListener("click", e => {
|
button.addEventListener("click", e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
main.append(conversationUI(conversation.id));
|
main.append(conversationUI(conversation.id, conversation.name));
|
||||||
nav.remove();
|
nav.remove();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -22,7 +24,7 @@ async function nav() {
|
||||||
_tap={b =>
|
_tap={b =>
|
||||||
b.addEventListener("click", e => {
|
b.addEventListener("click", e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
main.append(conversationUI("new"));
|
main.append(conversationUI("new", "New conversation"));
|
||||||
nav.remove();
|
nav.remove();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -37,7 +39,37 @@ async function nav() {
|
||||||
function conversationUI(id: string) {
|
function conversationUI(id: string) {
|
||||||
window.location.hash = `#${id}`;
|
window.location.hash = `#${id}`;
|
||||||
|
|
||||||
const socket = new WebSocket(`/api/conversation/${id}/connect`);
|
let socket: WebSocket;
|
||||||
|
let connected = false;
|
||||||
|
const connect = () => {
|
||||||
|
socket = new WebSocket(
|
||||||
|
`/api/conversation/${id}/connect` + (connected ? "?continue=1" : ""),
|
||||||
|
);
|
||||||
|
socket.addEventListener("open", () => (connected = true));
|
||||||
|
socket.addEventListener("close", () => (socket = connect()));
|
||||||
|
socket.addEventListener("error", ev => {
|
||||||
|
console.warn(ev);
|
||||||
|
// TODO: handle errors
|
||||||
|
});
|
||||||
|
return socket;
|
||||||
|
};
|
||||||
|
socket = connect();
|
||||||
|
|
||||||
|
const header = (
|
||||||
|
<header>
|
||||||
|
<h1 />
|
||||||
|
<button tabIndex={-1} type="button" className="danger">
|
||||||
|
delete
|
||||||
|
</button>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
const name = new Signal("");
|
||||||
|
name.subscribeImmediate(it => (header.querySelector("h1")!.textContent = it));
|
||||||
|
header.querySelector("button")!.addEventListener("click", async e => {
|
||||||
|
e.preventDefault();
|
||||||
|
await fetch(`/api/conversation/${id}`, { method: "DELETE" });
|
||||||
|
window.location.hash = "";
|
||||||
|
});
|
||||||
|
|
||||||
const chatlog = <section className="chatlog" />;
|
const chatlog = <section className="chatlog" />;
|
||||||
const inFlightMessages = new Map<string, Element>();
|
const inFlightMessages = new Map<string, Element>();
|
||||||
|
@ -64,6 +96,8 @@ function conversationUI(id: string) {
|
||||||
article.append(message.c);
|
article.append(message.c);
|
||||||
} else if ("d" in message) {
|
} else if ("d" in message) {
|
||||||
inFlightMessages.delete(message.d);
|
inFlightMessages.delete(message.d);
|
||||||
|
} else if ("n" in message) {
|
||||||
|
name.set(message.n);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scrolledToBottom) chatlog.scrollTop = chatlog.scrollHeight - chatlog.clientHeight;
|
if (scrolledToBottom) chatlog.scrollTop = chatlog.scrollHeight - chatlog.clientHeight;
|
||||||
|
@ -83,6 +117,7 @@ function conversationUI(id: string) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="conversation">
|
<section className="conversation">
|
||||||
|
{header}
|
||||||
{chatlog}
|
{chatlog}
|
||||||
{form}
|
{form}
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -51,6 +51,19 @@ main,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.conversation header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
font-size: smaller;
|
||||||
|
|
||||||
|
gap: 1em;
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.chatlog {
|
.chatlog {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from server.http import Starlette, Route, Request, Response, JSONResponse, WebSocketRoute, Mount
|
from server.http import Starlette, Route, Request, Response, JSONResponse, WebSocketRoute, Mount
|
||||||
from server.inference import list_conversations, connect_to_conversation
|
from server.inference import list_conversations, delete_conversation, connect_to_conversation
|
||||||
from starlette.staticfiles import StaticFiles
|
from starlette.staticfiles import StaticFiles
|
||||||
|
|
||||||
async def status(request: Request) -> Response:
|
async def status(request: Request) -> Response:
|
||||||
|
@ -8,6 +8,7 @@ async def status(request: Request) -> Response:
|
||||||
app = Starlette(debug=True, routes=[
|
app = Starlette(debug=True, routes=[
|
||||||
Route("/api/", status),
|
Route("/api/", status),
|
||||||
Route("/api/conversation", list_conversations, methods=["GET"]),
|
Route("/api/conversation", list_conversations, methods=["GET"]),
|
||||||
|
Route("/api/conversation/{conversation}", delete_conversation, methods=["DELETE"]),
|
||||||
WebSocketRoute("/api/conversation/{conversation}/connect", connect_to_conversation),
|
WebSocketRoute("/api/conversation/{conversation}/connect", connect_to_conversation),
|
||||||
Mount("/", app=StaticFiles(directory="client/web", html=True), name="client")
|
Mount("/", app=StaticFiles(directory="client/web", html=True), name="client")
|
||||||
])
|
])
|
||||||
|
|
|
@ -14,6 +14,13 @@ async def list_conversations(request: Request):
|
||||||
return JSONResponse(conversations)
|
return JSONResponse(conversations)
|
||||||
|
|
||||||
|
|
||||||
|
async def delete_conversation(request: Request):
|
||||||
|
conversation_id = request.path_params["conversation"]
|
||||||
|
db["responses"].delete_where("conversation_id = ?", [conversation_id])
|
||||||
|
db["conversations"].delete(conversation_id)
|
||||||
|
return JSONResponse({"status": "ok"})
|
||||||
|
|
||||||
|
|
||||||
async def connect_to_conversation(ws: WebSocket):
|
async def connect_to_conversation(ws: WebSocket):
|
||||||
continuing = bool(ws.query_params.get("continue"))
|
continuing = bool(ws.query_params.get("continue"))
|
||||||
conversation_id = ws.path_params["conversation"]
|
conversation_id = ws.path_params["conversation"]
|
||||||
|
@ -42,6 +49,8 @@ async def connect_to_conversation(ws: WebSocket):
|
||||||
await ws.send_text(json({"u": response.prompt.prompt})) # user
|
await ws.send_text(json({"u": response.prompt.prompt})) # user
|
||||||
await ws.send_text(json({"f": response.text_or_raise()})) # full
|
await ws.send_text(json({"f": response.text_or_raise()})) # full
|
||||||
|
|
||||||
|
await ws.send_text(json({"n": conversation.name}))
|
||||||
|
|
||||||
if conversation_id == "new":
|
if conversation_id == "new":
|
||||||
await ws.send_text(json({"i": conversation.id}))
|
await ws.send_text(json({"i": conversation.id}))
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue