refactor ai naming and make omni raw-json first

This commit is contained in:
Ruslan Bakiev
2026-02-23 09:32:59 +07:00
parent ab5370c831
commit 43b487ccec
13 changed files with 226 additions and 79 deletions

View File

@@ -68,8 +68,8 @@ model Team {
contacts Contact[]
calendarEvents CalendarEvent[]
deals Deal[]
conversations ChatConversation[]
chatMessages ChatMessage[]
aiConversations AiConversation[]
aiMessages AiMessage[]
omniThreads OmniThread[]
omniMessages OmniMessage[]
@@ -90,9 +90,9 @@ model User {
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
memberships TeamMember[]
conversations ChatConversation[] @relation("ConversationCreator")
chatMessages ChatMessage[] @relation("ChatAuthor")
memberships TeamMember[]
aiConversations AiConversation[] @relation("ConversationCreator")
aiMessages AiMessage[] @relation("ChatAuthor")
}
model TeamMember {
@@ -305,7 +305,7 @@ model DealStep {
@@index([status, dueAt])
}
model ChatConversation {
model AiConversation {
id String @id @default(cuid())
teamId String
createdByUserId String
@@ -313,15 +313,16 @@ model ChatConversation {
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
createdByUser User @relation("ConversationCreator", fields: [createdByUserId], references: [id], onDelete: Cascade)
messages ChatMessage[]
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
createdByUser User @relation("ConversationCreator", fields: [createdByUserId], references: [id], onDelete: Cascade)
messages AiMessage[]
@@index([teamId, updatedAt])
@@index([createdByUserId])
@@map("ChatConversation")
}
model ChatMessage {
model AiMessage {
id String @id @default(cuid())
teamId String
conversationId String
@@ -331,13 +332,14 @@ model ChatMessage {
planJson Json?
createdAt DateTime @default(now())
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
conversation ChatConversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
authorUser User? @relation("ChatAuthor", fields: [authorUserId], references: [id], onDelete: SetNull)
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
conversation AiConversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
authorUser User? @relation("ChatAuthor", fields: [authorUserId], references: [id], onDelete: SetNull)
@@index([createdAt])
@@index([teamId, createdAt])
@@index([conversationId, createdAt])
@@map("ChatMessage")
}
model FeedCard {

View File

@@ -62,6 +62,11 @@ function extractProviderMessageId(body: unknown): string | null {
return String(candidate);
}
function asObject(value: unknown): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
return value as Record<string, unknown>;
}
export function outboundDeliveryQueue() {
return new Queue<OutboundDeliveryJob, unknown, "deliver">(OUTBOUND_DELIVERY_QUEUE_NAME, {
connection: redisConnectionFromEnv(),
@@ -77,16 +82,26 @@ export async function enqueueOutboundDelivery(input: OutboundDeliveryJob, opts?:
const q = outboundDeliveryQueue();
const payload = (input.payload ?? null) as Prisma.InputJsonValue;
const existing = await prisma.omniMessage.findUnique({
where: { id: input.omniMessageId },
select: { rawJson: true },
});
const raw = asObject(existing?.rawJson);
const rawQueue = asObject(raw.queue);
const rawDeliveryRequest = asObject(raw.deliveryRequest);
await prisma.omniMessage.update({
where: { id: input.omniMessageId },
data: {
status: "PENDING",
rawJson: {
...raw,
queue: {
...rawQueue,
queueName: OUTBOUND_DELIVERY_QUEUE_NAME,
enqueuedAt: new Date().toISOString(),
},
deliveryRequest: {
...rawDeliveryRequest,
endpoint,
method: input.method ?? "POST",
channel: input.channel ?? null,
@@ -149,18 +164,24 @@ export function startOutboundDeliveryWorker() {
}
const providerMessageId = extractProviderMessageId(responseBody);
const raw = asObject(msg.rawJson);
const rawQueue = asObject(raw.queue);
const rawDeliveryRequest = asObject(raw.deliveryRequest);
await prisma.omniMessage.update({
where: { id: msg.id },
data: {
status: "SENT",
providerMessageId,
rawJson: {
...raw,
queue: {
...rawQueue,
queueName: OUTBOUND_DELIVERY_QUEUE_NAME,
completedAt: new Date().toISOString(),
attemptsMade: job.attemptsMade + 1,
},
deliveryRequest: {
...rawDeliveryRequest,
endpoint,
method,
channel: job.data.channel ?? null,
@@ -180,17 +201,23 @@ export function startOutboundDeliveryWorker() {
typeof job.opts.attempts === "number" && job.attemptsMade + 1 >= job.opts.attempts;
if (isLastAttempt) {
const raw = asObject(msg.rawJson);
const rawQueue = asObject(raw.queue);
const rawDeliveryRequest = asObject(raw.deliveryRequest);
await prisma.omniMessage.update({
where: { id: msg.id },
data: {
status: "FAILED",
rawJson: {
...raw,
queue: {
...rawQueue,
queueName: OUTBOUND_DELIVERY_QUEUE_NAME,
failedAt: new Date().toISOString(),
attemptsMade: job.attemptsMade + 1,
},
deliveryRequest: {
...rawDeliveryRequest,
endpoint,
method,
channel: job.data.channel ?? null,