AIAgent: dont save chat or message if failed

This commit is contained in:
Timofey
2025-11-13 21:32:16 +08:00
parent 91e5574d5e
commit 2a48b0ffab
9 changed files with 170 additions and 104 deletions

View File

@ -61,6 +61,32 @@ export const readMessages = async (
});
};
// Read single message by thread ID and message ID
export const readMessageById = async (
threadId: string,
messageId: string
): Promise<ThreadMessageLike | null> => {
const db = chatDB.getDB();
return new Promise((resolve, reject) => {
const transaction = db.transaction(["messages"], "readonly");
const store = transaction.objectStore("messages");
const request = store.get(messageId);
request.onerror = () => reject(request.error);
request.onsuccess = () => {
const result = request.result;
// Verify the message belongs to the specified thread
if (result && result.threadId === threadId) {
resolve(result.message);
} else {
resolve(null);
}
};
});
};
// Update message
export const updateMessage = async (
messageId: string,

View File

@ -14,7 +14,7 @@ export const saveThread = async (
thread: Omit<Thread, "createdAt" | "updatedAt">
): Promise<void> => {
const db = chatDB.getDB();
return new Promise((resolve, reject) => {
const transaction = db.transaction(["threads"], "readwrite");
const store = transaction.objectStore("threads");
@ -34,12 +34,12 @@ export const saveThread = async (
export const getThread = async (threadId: string): Promise<Thread | null> => {
const db = chatDB.getDB();
return new Promise((resolve, reject) => {
return new Promise((resolve) => {
const transaction = db.transaction(["threads"], "readonly");
const store = transaction.objectStore("threads");
const request = store.get(threadId);
request.onerror = () => reject(request.error);
request.onerror = () => resolve(null);
request.onsuccess = () => resolve(request.result || null);
});
};
@ -56,9 +56,7 @@ export const getAllThreads = async (): Promise<Thread[]> => {
request.onerror = () => reject(request.error);
request.onsuccess = () => {
const threads = request.result.sort(
(a, b) => b.updatedAt - a.updatedAt
);
const threads = request.result.sort((a, b) => b.updatedAt - a.updatedAt);
resolve(threads);
};
});
@ -74,10 +72,10 @@ export const updateThread = async (
return new Promise((resolve, reject) => {
const transaction = db.transaction(["threads"], "readwrite");
const store = transaction.objectStore("threads");
// First get the existing thread
const getRequest = store.get(threadId);
getRequest.onerror = () => reject(getRequest.error);
getRequest.onsuccess = () => {
const existingThread = getRequest.result;
@ -112,4 +110,4 @@ export const deleteThread = async (threadId: string): Promise<void> => {
request.onerror = () => reject(request.error);
request.onsuccess = () => resolve();
});
};
};

View File

@ -15,6 +15,7 @@ import useThreadsStore from "@/store/useThreadsStore";
import useServersStore from "@/store/useServersStore";
import useProviders from "@/store/useProviders";
import useModelsStore from "@/store/useModelsStore";
import { getThread } from "@/database/metadata";
type UseMessagesProps = {
isReady: boolean;
@ -257,15 +258,52 @@ const useMessages = ({ isReady }: UseMessagesProps) => {
attachments: message.attachments,
};
if (messages.length === 0) {
provider.createChatName(message.content[0].text).then((title) => {
const existingThread = await getThread(threadId);
if (!existingThread) {
let textForTitle = "";
for (const msg of messages) {
// Skip messages with errors
if (msg.status?.type === "incomplete" && msg.status?.error) continue;
textForTitle +=
typeof msg.content === "string"
? msg.content
: msg.content[0].type === "text"
? msg.content[0].text
: "";
textForTitle += "\n\n";
}
textForTitle += "\n\n" + message.content[0].text;
provider.createChatName(textForTitle).then(async (title) => {
if (!title) return;
insertThread(title);
// Save all messages from the store to the database (skip error messages)
for (const msg of messages) {
// Skip messages with errors
if (msg.status?.type === "incomplete" && msg.status?.error) continue;
await createMessage(threadId, crypto.randomUUID(), msg);
}
// Save the new user message
await createMessage(threadId, crypto.randomUUID(), userMessage);
});
} else {
insertNewMessageToThread();
}
createMessage(threadId, crypto.randomUUID(), userMessage);
const createMessages = async () => {
await createMessage(threadId, crypto.randomUUID(), userMessage);
};
createMessages();
}
addMessage(userMessage);

View File

@ -83,7 +83,7 @@ class AnthropicProvider
async createChatName(message: string) {
try {
if (!this.client) return message.substring(0, 25);
if (!this.client) return "";
const response = await this.client.messages.create({
messages: [{ role: "user", content: message }],
@ -97,7 +97,7 @@ class AnthropicProvider
return title ?? message.substring(0, 25);
} catch {
return message.substring(0, 25);
return "";
}
}

View File

@ -107,7 +107,7 @@ class Provider {
};
createChatName = async (message: string) => {
if (!this.currentProvider) return message.substring(0, 25);
if (!this.currentProvider) return "";
return this.currentProvider.createChatName(message);
};

View File

@ -75,7 +75,7 @@ class OllamaProvider
async createChatName(message: string) {
try {
if (!this.client) return message.substring(0, 25);
if (!this.client) return "";
const systemMsg = {
role: "system",
@ -92,7 +92,7 @@ class OllamaProvider
return title ?? message.substring(0, 25);
} catch {
return message.substring(0, 25);
return "";
}
}

View File

@ -83,7 +83,7 @@ class OpenAIProvider
async createChatName(message: string) {
try {
if (!this.client) return message.substring(0, 25);
if (!this.client) return "";
const systemMessage: ChatCompletionSystemMessageParam = {
role: "system",
@ -100,7 +100,7 @@ class OpenAIProvider
return title ?? message.substring(0, 25);
} catch {
return message.substring(0, 25);
return "";
}
}

View File

@ -81,7 +81,7 @@ class TogetherProvider
async createChatName(message: string) {
try {
if (!this.client) return message.substring(0, 25);
if (!this.client) return "";
const systemMessage: ChatCompletionSystemMessageParam = {
role: "system",
@ -98,7 +98,7 @@ class TogetherProvider
return title ?? message.substring(0, 25);
} catch {
return message.substring(0, 25);
return "";
}
}