feat(chat): robust thread support (complex)
This commit is contained in:
1 parent
c588a12160
commit
73b789b586
3 files changed
+77
-16
No files matched your search
@@ -17,6 +17,17 @@ def message_json(msg):
|
|||||||
"threadId": msg.thread_id,
|
"threadId": msg.thread_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def thread_json(it):
|
||||||
|
return {
|
||||||
|
'id': it.id,
|
||||||
|
'parentId': it.parent_id,
|
||||||
|
'name': it.name,
|
||||||
|
'description': it.description,
|
||||||
|
'firstMessageId': it.first_message_id,
|
||||||
|
'lastMessageId': it.last_message_id,
|
||||||
|
'messageCount': it.message_count,
|
||||||
|
}
|
||||||
|
|
||||||
async def aggregate_thread(thread_id):
|
async def aggregate_thread(thread_id):
|
||||||
print(f"aggregate {thread_id}")
|
print(f"aggregate {thread_id}")
|
||||||
query = db.Message.filter(thread_id=thread_id)
|
query = db.Message.filter(thread_id=thread_id)
|
||||||
@@ -126,15 +137,7 @@ class ChatMixin:
|
|||||||
|
|
||||||
async def get_chat_threads(self, chat_id):
|
async def get_chat_threads(self, chat_id):
|
||||||
threads = await db.Thread.filter(chat_id=chat_id).all()
|
threads = await db.Thread.filter(chat_id=chat_id).all()
|
||||||
return [{
|
return [thread_json(it) for it in threads]
|
||||||
'id': it.id,
|
|
||||||
'parentId': it.parent_id,
|
|
||||||
'name': it.name,
|
|
||||||
'description': it.description,
|
|
||||||
'firstMessageId': it.first_message_id,
|
|
||||||
'lastMessageId': it.last_message_id,
|
|
||||||
'messageCount': it.message_count,
|
|
||||||
} for it in threads]
|
|
||||||
|
|
||||||
async def get_thread_messages(self, chat_id, thread_id, limit_message_id=None):
|
async def get_thread_messages(self, chat_id, thread_id, limit_message_id=None):
|
||||||
chat = await self.get_chat(chat_id)
|
chat = await self.get_chat(chat_id)
|
||||||
@@ -171,6 +174,16 @@ class ChatMixin:
|
|||||||
for msg in messages:
|
for msg in messages:
|
||||||
self.notify_message_to_user(chat.user_id, msg, True)
|
self.notify_message_to_user(chat.user_id, msg, True)
|
||||||
|
|
||||||
|
|
||||||
|
# Manually notify thread updates
|
||||||
|
if chat.user_id in self.user_connections:
|
||||||
|
children = await db.Thread.filter(parent_id=new_id).all()
|
||||||
|
packets = [dict(thread_json(it), action='thread-update') for it in children]
|
||||||
|
|
||||||
|
for channel in self.user_connections[chat.user_id]:
|
||||||
|
for packet in packets:
|
||||||
|
asyncio.create_task(channel.put(packet))
|
||||||
|
|
||||||
return new_id
|
return new_id
|
||||||
|
|
||||||
async def add_agent_to_chat(self, chat_id, agent_id):
|
async def add_agent_to_chat(self, chat_id, agent_id):
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ async def chat_completion(app,
|
|||||||
agent_run=None
|
agent_run=None
|
||||||
):
|
):
|
||||||
# TESTING OVERRIDE
|
# TESTING OVERRIDE
|
||||||
return await mock_completion(app, agent_run)
|
# return await mock_completion(app, agent_run)
|
||||||
db_model = (await app.get_model(model_id)).value
|
db_model = (await app.get_model(model_id)).value
|
||||||
|
|
||||||
model_engine = db_model['engine']
|
model_engine = db_model['engine']
|
||||||
|
|||||||
+54
-6
@@ -48,6 +48,19 @@ function selectEarliest (messages) {
|
|||||||
return selected
|
return selected
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function messageCopy (it) {
|
||||||
|
return {
|
||||||
|
id: it.id,
|
||||||
|
type: it.kind,
|
||||||
|
format: it.format,
|
||||||
|
subkind: it.subkind,
|
||||||
|
sender: it.sender,
|
||||||
|
content: it.content,
|
||||||
|
threadId: it.threadId,
|
||||||
|
time: it.time,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export class Thread {
|
export class Thread {
|
||||||
constructor (obj, session) {
|
constructor (obj, session) {
|
||||||
Object.assign(this, {
|
Object.assign(this, {
|
||||||
@@ -159,6 +172,7 @@ export class ChatSession {
|
|||||||
this._messageNonce = 1;
|
this._messageNonce = 1;
|
||||||
this._unsubscribeChat = null;
|
this._unsubscribeChat = null;
|
||||||
this._unsubscribeRuns = null;
|
this._unsubscribeRuns = null;
|
||||||
|
this._unsubscribeThreads = null;
|
||||||
this._runListener = null;
|
this._runListener = null;
|
||||||
this._rescroll = null;
|
this._rescroll = null;
|
||||||
}
|
}
|
||||||
@@ -211,6 +225,14 @@ export class ChatSession {
|
|||||||
|
|
||||||
this._unsubscribeChat = backend.onChatMessages(chatId, it => this.receiveMessage(it));
|
this._unsubscribeChat = backend.onChatMessages(chatId, it => this.receiveMessage(it));
|
||||||
this._unsubscribeRuns = runs.onChatMessage(chatId, event => this.trackRun(event));
|
this._unsubscribeRuns = runs.onChatMessage(chatId, event => this.trackRun(event));
|
||||||
|
this._unsubscribeThreads = backend.onAction('thread-update', event => {
|
||||||
|
let thread = this.threadMap[event.id];
|
||||||
|
if (thread) {
|
||||||
|
let data = {...event};
|
||||||
|
delete data.action;
|
||||||
|
thread.update(data)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
// Load threads
|
// Load threads
|
||||||
let {threads} = await backend.sendAction("get-chat-threads", {chatId});
|
let {threads} = await backend.sendAction("get-chat-threads", {chatId});
|
||||||
@@ -241,6 +263,8 @@ export class ChatSession {
|
|||||||
this._unsubscribeChat = null;
|
this._unsubscribeChat = null;
|
||||||
if (this._unsubscribeRuns) this._unsubscribeRuns();
|
if (this._unsubscribeRuns) this._unsubscribeRuns();
|
||||||
this._unsubscribeRuns = null;
|
this._unsubscribeRuns = null;
|
||||||
|
if (this._unsubscribeThreads) this._unsubscribeThreads();
|
||||||
|
this._unsubscribeThreads = null;
|
||||||
if (this._runListener) this._runListener.cancel();
|
if (this._runListener) this._runListener.cancel();
|
||||||
this._runListener = null;
|
this._runListener = null;
|
||||||
}
|
}
|
||||||
@@ -435,15 +459,17 @@ export class ChatSession {
|
|||||||
|
|
||||||
if (this.creatingThread.value) {
|
if (this.creatingThread.value) {
|
||||||
|
|
||||||
// Send the target message to a fork
|
// Send the target message to a fork if it doesn't start its thread
|
||||||
let res = await backend.sendAction("fork-chat-thread", {
|
if (previousThreadId == messageThreadId) {
|
||||||
|
await backend.sendAction("fork-chat-thread", {
|
||||||
chatId: this.chatId,
|
chatId: this.chatId,
|
||||||
threadId: previousThreadId,
|
threadId: previousThreadId,
|
||||||
messageId,
|
messageId,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Then create a new fork again for the new message
|
// Create a new fork for the new message
|
||||||
res = await backend.sendAction("fork-chat-thread", {
|
let res = await backend.sendAction("fork-chat-thread", {
|
||||||
chatId: this.chatId,
|
chatId: this.chatId,
|
||||||
threadId: previousThreadId,
|
threadId: previousThreadId,
|
||||||
});
|
});
|
||||||
@@ -598,8 +624,28 @@ export class ChatSession {
|
|||||||
this.currentThreadId.value = threadId;
|
this.currentThreadId.value = threadId;
|
||||||
this.activeThreadIds = [];
|
this.activeThreadIds = [];
|
||||||
|
|
||||||
// Activate and load all threads in the ancestry
|
|
||||||
let thread = this.getThread(threadId);
|
let thread = this.getThread(threadId);
|
||||||
|
|
||||||
|
// If the thread has children, find the most recent leaf
|
||||||
|
let stack = [thread]
|
||||||
|
let lastMessage = null;
|
||||||
|
while (stack.length) {
|
||||||
|
let next = stack.pop();
|
||||||
|
|
||||||
|
let last = next.getLastMessage();
|
||||||
|
if (last && (!lastMessage || last.id > lastMessage.id)) {
|
||||||
|
lastMessage = last;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack = stack.concat(thread.children);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invariably activate the thread with the most recent message
|
||||||
|
if (lastMessage) {
|
||||||
|
thread = this.getThread(lastMessage.threadId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Activate and load all threads in the ancestry
|
||||||
while (true) {
|
while (true) {
|
||||||
this.activeThreadIds.push(thread.id);
|
this.activeThreadIds.push(thread.id);
|
||||||
|
|
||||||
@@ -624,6 +670,8 @@ export class ChatSession {
|
|||||||
thread = this.getThread(thread.parentId);
|
thread = this.getThread(thread.parentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.computeChatEntries();
|
this.computeChatEntries();
|
||||||
this.rescroll();
|
this.rescroll();
|
||||||
}
|
}
|
||||||
@@ -732,7 +780,7 @@ export class ChatSession {
|
|||||||
firstMessage ? {id: firstMessage.id, position: 'before'} :
|
firstMessage ? {id: firstMessage.id, position: 'before'} :
|
||||||
null;
|
null;
|
||||||
|
|
||||||
if (!attach) return;
|
if (!attach) continue;
|
||||||
|
|
||||||
headers.push({
|
headers.push({
|
||||||
// claim just before id
|
// claim just before id
|
||||||
|
|||||||
Reference in new issue
Block a user