Skip to content

Commit 29db915

Browse files
committed
improvement(chat): stop loading a transcript the v2 route never reads
Nothing caps a chat transcript — no per-chat message limit on write, no pruning — and the v2 route keys continuity by `chatId`, so it read the whole thing on every resumed turn and dropped it. Opt out there. The load stays the default because the copilot send path does consume it.
1 parent a62dd79 commit 29db915

2 files changed

Lines changed: 20 additions & 4 deletions

File tree

apps/sim/app/api/v2/chat/route.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ export const POST = withRouteHandler(
177177
// Chat block do, both of which post a single message with a chat id.
178178
const resolvedChat = await resolveOrCreateChat({
179179
...(conversationId ? { chatId: conversationId } : {}),
180+
includeTranscript: false,
180181
userId,
181182
workspaceId,
182183
model: MOTHERSHIP_CHAT_DEFAULT_MODEL,

apps/sim/lib/copilot/chat/lifecycle.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,8 @@ export async function getAccessibleCopilotChat(
212212
*/
213213
export async function getAccessibleCopilotChatWithMessages(
214214
chatId: string,
215-
userId: string
215+
userId: string,
216+
options?: { includeTranscript?: boolean }
216217
): Promise<CopilotChatDetailRow | null> {
217218
const [chat] = await db
218219
.select(copilotChatDetailColumns)
@@ -223,7 +224,14 @@ export async function getAccessibleCopilotChatWithMessages(
223224
const authorized = await authorizeCopilotChatRow(chat, chatId, userId)
224225
if (!authorized) return null
225226

226-
const messages = await loadCopilotChatMessages(chatId)
227+
/**
228+
* The transcript is unbounded — no per-chat message cap on write and no
229+
* pruning — so a caller that only needs the chat's scope should not pay to
230+
* materialize it. Every check `resolveOrCreateChat` runs reads detail
231+
* columns only, so an empty list stays a truthful "not loaded" rather than
232+
* "no messages" for the callers that opt out.
233+
*/
234+
const messages = options?.includeTranscript === false ? [] : await loadCopilotChatMessages(chatId)
227235
return { ...authorized, messages }
228236
}
229237

@@ -245,15 +253,22 @@ export async function resolveOrCreateChat(params: {
245253
model: string
246254
type?: 'mothership' | 'copilot'
247255
title?: string
256+
/**
257+
* Skips loading the transcript on the resume path. For a caller that keys
258+
* continuity by `chatId` alone and never reads `conversationHistory`.
259+
*/
260+
includeTranscript?: boolean
248261
}): Promise<ChatLoadResult> {
249-
const { chatId, userId, workflowId, workspaceId, model, type, title } = params
262+
const { chatId, userId, workflowId, workspaceId, model, type, title, includeTranscript } = params
250263

251264
if (workspaceId) {
252265
await assertActiveWorkspaceAccess(workspaceId, userId)
253266
}
254267

255268
if (chatId) {
256-
const chat = await getAccessibleCopilotChatWithMessages(chatId, userId)
269+
const chat = await getAccessibleCopilotChatWithMessages(chatId, userId, {
270+
includeTranscript,
271+
})
257272

258273
if (chat) {
259274
if (workflowId && chat.workflowId !== workflowId) {

0 commit comments

Comments
 (0)