mirror of
https://github.com/geoffsee/open-gsio.git
synced 2025-09-08 22:56:46 +00:00
saves a message
This commit is contained in:

committed by
Geoff Seemueller

parent
810846bb3c
commit
9e6ef975a9
148
src/stores/MessageEditorStore.ts
Normal file
148
src/stores/MessageEditorStore.ts
Normal file
@@ -0,0 +1,148 @@
|
||||
import {types, Instance} from "mobx-state-tree";
|
||||
import clientChatStore from "./ClientChatStore";
|
||||
import UserOptionsStore from "./UserOptionsStore";
|
||||
import Message from "../models/Message";
|
||||
import {MessagesStore} from "./MessagesStore";
|
||||
|
||||
export const MessageEditorStore = types
|
||||
.compose(
|
||||
MessagesStore,
|
||||
types.model("MessageEditorStore", {
|
||||
editedContent: types.optional(types.string, ""),
|
||||
messageId: types.optional(types.string, "")
|
||||
})
|
||||
)
|
||||
.views((self) => ({
|
||||
getMessage() {
|
||||
// Find the message in clientChatStore by ID
|
||||
if (!self.messageId) return null;
|
||||
|
||||
const message = clientChatStore.items.find(item => item.id === self.messageId);
|
||||
return message || null;
|
||||
}
|
||||
}))
|
||||
.actions((self) => ({
|
||||
setEditedContent(content: string) {
|
||||
self.editedContent = content;
|
||||
},
|
||||
setMessage(message: Instance<typeof Message>) {
|
||||
self.messageId = message.id;
|
||||
self.editedContent = message.content;
|
||||
},
|
||||
onCancel() {
|
||||
self.messageId = "";
|
||||
self.editedContent = "";
|
||||
},
|
||||
handleSave: async () => {
|
||||
// Get the message using the ID
|
||||
const message = self.getMessage();
|
||||
|
||||
// Check if message reference is still valid
|
||||
if (!message) {
|
||||
// Message reference is no longer valid, just cancel the edit
|
||||
self.onCancel();
|
||||
return;
|
||||
}
|
||||
|
||||
// Store the content we want to update
|
||||
const contentToUpdate = self.editedContent;
|
||||
|
||||
try {
|
||||
// Use the editMessage function from MessagesStore
|
||||
const success = clientChatStore.editMessage(message, contentToUpdate);
|
||||
if (!success) {
|
||||
// Message not found in the items array, just cancel
|
||||
self.onCancel();
|
||||
return;
|
||||
}
|
||||
|
||||
// Set follow mode and loading state
|
||||
UserOptionsStore.setFollowModeEnabled(true);
|
||||
clientChatStore.setIsLoading(true);
|
||||
|
||||
try {
|
||||
// Add a small delay before adding the assistant message (for better UX)
|
||||
await new Promise((r) => setTimeout(r, 500));
|
||||
|
||||
// Add an empty assistant message to clientChatStore's items
|
||||
clientChatStore.add(Message.create({content: "", role: "assistant"}));
|
||||
// Use clientChatStore for the API call since it has the model property
|
||||
const payload = {messages: clientChatStore.items.slice(), model: clientChatStore.model};
|
||||
|
||||
// Make API call
|
||||
const response = await fetch("/api/chat", {
|
||||
method: "POST",
|
||||
headers: {"Content-Type": "application/json"},
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
|
||||
if (response.status === 429) {
|
||||
clientChatStore.updateLast("Too many requests • please slow down.");
|
||||
clientChatStore.setIsLoading(false);
|
||||
UserOptionsStore.setFollowModeEnabled(false);
|
||||
return;
|
||||
}
|
||||
if (response.status > 200) {
|
||||
clientChatStore.updateLast("Error • something went wrong.");
|
||||
clientChatStore.setIsLoading(false);
|
||||
UserOptionsStore.setFollowModeEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const {streamUrl} = await response.json();
|
||||
const eventSource = new EventSource(streamUrl);
|
||||
|
||||
eventSource.onmessage = (event) => {
|
||||
try {
|
||||
const parsed = JSON.parse(event.data);
|
||||
if (parsed.type === "error") {
|
||||
clientChatStore.updateLast(parsed.error);
|
||||
clientChatStore.setIsLoading(false);
|
||||
UserOptionsStore.setFollowModeEnabled(false);
|
||||
eventSource.close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (parsed.type === "chat" && parsed.data.choices[0]?.finish_reason === "stop") {
|
||||
clientChatStore.appendLast(parsed.data.choices[0]?.delta?.content ?? "");
|
||||
clientChatStore.setIsLoading(false);
|
||||
UserOptionsStore.setFollowModeEnabled(false);
|
||||
eventSource.close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (parsed.type === "chat") {
|
||||
clientChatStore.appendLast(parsed.data.choices[0]?.delta?.content ?? "");
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("stream parse error", err);
|
||||
}
|
||||
};
|
||||
|
||||
eventSource.onerror = () => {
|
||||
clientChatStore.updateLast("Error • connection lost.");
|
||||
clientChatStore.setIsLoading(false);
|
||||
UserOptionsStore.setFollowModeEnabled(false);
|
||||
eventSource.close();
|
||||
};
|
||||
} catch (err) {
|
||||
console.error("sendMessage", err);
|
||||
clientChatStore.updateLast("Sorry • network error.");
|
||||
clientChatStore.setIsLoading(false);
|
||||
UserOptionsStore.setFollowModeEnabled(false);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Error in handleSave:", err);
|
||||
// If any error occurs, just cancel the edit
|
||||
self.onCancel();
|
||||
return;
|
||||
}
|
||||
|
||||
// Always clean up at the end
|
||||
self.onCancel();
|
||||
}
|
||||
}));
|
||||
|
||||
const messageEditorStore = MessageEditorStore.create();
|
||||
|
||||
export default messageEditorStore;
|
Reference in New Issue
Block a user