File size: 2,616 Bytes
346fcd8
 
 
 
cb5990d
 
 
 
346fcd8
cb5990d
346fcd8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cb5990d
 
346fcd8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cb5990d
 
 
 
346fcd8
 
cb5990d
346fcd8
 
 
cb5990d
346fcd8
 
 
 
 
 
cb5990d
 
346fcd8
cb5990d
 
 
 
 
 
346fcd8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { tick } from "svelte";
import { UrlDependency } from "$lib/types/UrlDependency";
import file2base64 from "$lib/utils/file2base64";
import { ERROR_MESSAGES } from "$lib/stores/errors";
import type { WriteMessageContext, WriteMessageParams } from "$lib/types/MessageContext";
import { ConversationTreeManager } from "./message/ConversationTreeManager";
import { MessageStreamHandler } from "./message/MessageStreamHandler";
import { base } from "$app/paths";

export type { WriteMessageContext, WriteMessageParams };

export async function writeMessage(
	ctx: WriteMessageContext,
	params: WriteMessageParams
): Promise<void> {
	const {
		prompt,
		messageId = ctx.messagesPath.at(-1)?.id ?? undefined,
		isRetry = false,
		isContinue = false,
		personaId,
	} = params;

	const conversationId = ctx.page.params.id;
	if (!conversationId) {
		console.error("No conversation ID available");
		return;
	}

	const treeManager = new ConversationTreeManager(ctx);
	const streamHandler = new MessageStreamHandler(ctx, treeManager);

	try {
		ctx.setIsAborted(false);
		ctx.setLoading(true);
		ctx.setPending(true);

		const base64Files = await Promise.all(
			(ctx.files ?? []).map((file) =>
				file2base64(file).then((value) => ({
					type: "base64" as const,
					value,
					mime: file.type,
					name: file.name,
				}))
			)
		);

		const { messageToWriteToId, navigateToMessageId } = treeManager.prepareMessageForWrite(
			params,
			base64Files
		);
		const userMessage = ctx.messages.find((message) => message.id === messageId);

		await streamHandler.handleStream(
			conversationId,
			{
				base,
				prompt,
				messageId,
				isRetry,
				isContinue,
				files: isRetry ? userMessage?.files : base64Files,
				personaId,
			},
			messageToWriteToId
		);

		if (navigateToMessageId) {
			await tick();
			const url = new URL(window.location.href);
			url.searchParams.set("msgId", navigateToMessageId);
			url.searchParams.set("scrollTo", "true");
			await ctx.goto(url.toString(), { replaceState: false, noScroll: true });
		}
	} catch (err) {
		if (err instanceof Error && err.message.includes("overloaded")) {
			ctx.setError("Too much traffic, please try again.");
		} else if (err instanceof Error && err.message.includes("429")) {
			ctx.setError(ERROR_MESSAGES.rateLimited);
		} else if (err instanceof Error) {
			ctx.setError(err.message);
		} else {
			ctx.setError(ERROR_MESSAGES.default);
		}
		console.error(err);
	} finally {
		await ctx.invalidate(UrlDependency.Conversation);
		await ctx.invalidate(UrlDependency.ConversationList);

		ctx.setLoading(false);
		ctx.setPending(false);
	}
}