fix(api): route group follow-ups to the waiting member bot
Group threads/followUp always steered to members[0], so a follow-up while a later member had waiting_input went to the wrong bot or started a fresh run on the first member instead of continuing the ask. Resolve the target bot like group sends: prefer waiting ask/takeover on any member, then the newest steerable active run, then @mentions, then the default first member. Extract followUpGroupThreadMessage and add regression tests. Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>
This commit is contained in:
parent
44d1bc7277
commit
f5265924ba
@ -180,6 +180,7 @@ import {
|
|||||||
shouldForwardPeerThreadEvent,
|
shouldForwardPeerThreadEvent,
|
||||||
} from "./thread-message-pages.js";
|
} from "./thread-message-pages.js";
|
||||||
import {
|
import {
|
||||||
|
followUpGroupThreadMessage,
|
||||||
reactToThreadMessage,
|
reactToThreadMessage,
|
||||||
resolveThreadTarget,
|
resolveThreadTarget,
|
||||||
sendThreadMessage,
|
sendThreadMessage,
|
||||||
@ -1543,79 +1544,8 @@ export function createRouter(deps: RouterDeps) {
|
|||||||
}
|
}
|
||||||
return { ok: true as const };
|
return { ok: true as const };
|
||||||
}
|
}
|
||||||
const committed = await deps.prisma.$transaction(async (tx) => {
|
const committed = await followUpGroupThreadMessage(deps, context.actor, target, {
|
||||||
await lockOwnedGroup(tx, context.actor, target.groupId);
|
text: input.text,
|
||||||
const group = await tx.chatGroup.findFirst({
|
|
||||||
where: {
|
|
||||||
id: target.groupId,
|
|
||||||
archivedAt: null,
|
|
||||||
thread: { id: target.threadId },
|
|
||||||
},
|
|
||||||
include: { members: { orderBy: { createdAt: "asc" } } },
|
|
||||||
});
|
|
||||||
const botId = group?.members[0]?.botId;
|
|
||||||
if (!botId) throw new IsolationError();
|
|
||||||
const blocks = [{ kind: "text" as const, text: input.text }];
|
|
||||||
const message = await createThreadMessageInTransaction(tx, {
|
|
||||||
threadId: target.threadId,
|
|
||||||
role: "user",
|
|
||||||
blocks,
|
|
||||||
});
|
|
||||||
const active = await tx.run.findFirst({
|
|
||||||
where: {
|
|
||||||
threadId: target.threadId,
|
|
||||||
botId,
|
|
||||||
status: { in: [...ACTIVE_RUN_STATUSES] },
|
|
||||||
},
|
|
||||||
select: { id: true },
|
|
||||||
});
|
|
||||||
let run: { id: string } | null = null;
|
|
||||||
if (!active) {
|
|
||||||
const task = await tx.task.create({
|
|
||||||
data: {
|
|
||||||
spaceId: context.actor.spaceId,
|
|
||||||
botId,
|
|
||||||
threadId: target.threadId,
|
|
||||||
userId: context.actor.userId,
|
|
||||||
prompt: input.text,
|
|
||||||
status: "queued",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
run = await tx.run.create({
|
|
||||||
data: {
|
|
||||||
spaceId: context.actor.spaceId,
|
|
||||||
botId,
|
|
||||||
threadId: target.threadId,
|
|
||||||
taskId: task.id,
|
|
||||||
userId: context.actor.userId,
|
|
||||||
status: "queued",
|
|
||||||
trigger: "follow_up",
|
|
||||||
sourceMessageId: message.id,
|
|
||||||
},
|
|
||||||
select: { id: true },
|
|
||||||
});
|
|
||||||
await tx.message.update({ where: { id: message.id }, data: { runId: run.id } });
|
|
||||||
} else {
|
|
||||||
await tx.steeringMessage.create({
|
|
||||||
data: {
|
|
||||||
messageId: message.id,
|
|
||||||
botId,
|
|
||||||
userId: context.actor.userId,
|
|
||||||
runId: active.id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
await tx.message.update({ where: { id: message.id }, data: { runId: active.id } });
|
|
||||||
}
|
|
||||||
const event = await appendEventInTransaction(tx, {
|
|
||||||
spaceId: context.actor.spaceId,
|
|
||||||
threadId: target.threadId,
|
|
||||||
botId,
|
|
||||||
type: "thread.message.created",
|
|
||||||
runId: run?.id ?? active?.id,
|
|
||||||
payload: { messageId: message.id, role: "user", blocks },
|
|
||||||
});
|
|
||||||
await touchGroupUpdatedAt(tx, target.groupId);
|
|
||||||
return { runId: run?.id, eventSeq: event.seq };
|
|
||||||
});
|
});
|
||||||
await deps.events.notify(target.threadId, committed.eventSeq).catch((error) => {
|
await deps.events.notify(target.threadId, committed.eventSeq).catch((error) => {
|
||||||
getLogger().error("group follow-up realtime notification", error);
|
getLogger().error("group follow-up realtime notification", error);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user