Skip to content

Commit 0277037

Browse files
Bill LeoutsakosBill Leoutsakos
authored andcommitted
Merge remote-tracking branch 'origin/staging' into investigate/oracle-fusion-erp-integration
2 parents 12599c8 + ff47aae commit 0277037

2 files changed

Lines changed: 24 additions & 4 deletions

File tree

apps/sim/lib/copilot/request/lifecycle/start.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { db } from '@sim/db'
33
import { copilotChats } from '@sim/db/schema'
44
import { createLogger } from '@sim/logger'
55
import { getErrorMessage } from '@sim/utils/errors'
6-
import { eq } from 'drizzle-orm'
6+
import { and, eq, isNull } from 'drizzle-orm'
77
import {
88
assertBillingAttributionSnapshot,
99
type BillingAttributionSnapshot,
@@ -489,7 +489,17 @@ function fireTitleGeneration(params: {
489489
})
490490
.then(async (title) => {
491491
if (!title) return
492-
await db.update(copilotChats).set({ title }).where(eq(copilotChats.id, chatId))
492+
// Only stamp the generated title while the chat has none. Title
493+
// generation is fired at turn start and resolves asynchronously, so a
494+
// user could rename the chat in the meantime; the `isNull` guard makes
495+
// the write lose that race instead of clobbering the explicit rename.
496+
const stamped = await db
497+
.update(copilotChats)
498+
.set({ title })
499+
.where(and(eq(copilotChats.id, chatId), isNull(copilotChats.title)))
500+
.returning({ id: copilotChats.id })
501+
// The rename won — do not announce a title the row no longer holds.
502+
if (stamped.length === 0) return
493503
await publisher.publish({
494504
type: MothershipStreamV1EventType.session,
495505
payload: { kind: MothershipStreamV1SessionKind.title, title },

apps/sim/lib/mothership/inbox/executor.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { copilotChats, db, mothershipInboxTask, user, workspace } from '@sim/db'
22
import { createLogger } from '@sim/logger'
33
import { getErrorMessage } from '@sim/utils/errors'
44
import { generateId } from '@sim/utils/id'
5-
import { and, eq, sql } from 'drizzle-orm'
5+
import { and, eq, isNull, sql } from 'drizzle-orm'
66
import { getActivelyBannedUserIds, isEmailBlocked } from '@/lib/auth/ban'
77
import { resolveBillingAttribution } from '@/lib/billing/core/billing-attribution'
88
import { resolveOrCreateChat } from '@/lib/copilot/chat/lifecycle'
@@ -167,7 +167,17 @@ export async function executeInboxTask(taskId: string): Promise<void> {
167167
})
168168
.then(async (title) => {
169169
if (title && chatId) {
170-
await db.update(copilotChats).set({ title }).where(eq(copilotChats.id, chatId))
170+
// Only stamp the generated title while the chat has none. This
171+
// resolves asynchronously, so a user could rename the chat in the
172+
// meantime; the `isNull` guard makes the write lose that race
173+
// instead of clobbering the explicit rename.
174+
const stamped = await db
175+
.update(copilotChats)
176+
.set({ title })
177+
.where(and(eq(copilotChats.id, chatId), isNull(copilotChats.title)))
178+
.returning({ id: copilotChats.id })
179+
// The rename won — do not announce a title the row no longer holds.
180+
if (stamped.length === 0) return
171181
chatPubSub?.publishStatusChanged({
172182
workspaceId: ws.id,
173183
chatId,

0 commit comments

Comments
 (0)