Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 28 additions & 10 deletions apps/sim/app/api/mothership/chats/[chatId]/fork/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ export const POST = withRouteHandler(
await assertActiveWorkspaceAccess(parent.workspaceId, userId)
}

if (parent.conversationId) {
return createBadRequestResponse('Cannot fork a chat with an active stream')
}
Comment thread
waleedlatif1 marked this conversation as resolved.
Outdated

// Find the fork point in the Sim-side messages array.
const messages = Array.isArray(parent.messages) ? (parent.messages as PersistedMessage[]) : []
const forkIdx = messages.findIndex((m) => m.id === upToMessageId)
Expand All @@ -84,6 +88,7 @@ export const POST = withRouteHandler(
id: newId,
userId,
workspaceId: parent.workspaceId,
workflowId: parent.workflowId,
type: parent.type,
title,
model: parent.model,
Expand All @@ -103,32 +108,45 @@ export const POST = withRouteHandler(
}

// Clone copilot-service conversation state (messages, active_messages, memory files).
// Best-effort: if the copilot service doesn't have a row for the source chat yet, skip.
const copilotHeaders: Record<string, string> = { 'Content-Type': 'application/json' }
if (env.COPILOT_API_KEY) {
copilotHeaders['x-api-key'] = env.COPILOT_API_KEY
}
let copilotFailed = false
try {
const copilotHeaders: Record<string, string> = { 'Content-Type': 'application/json' }
if (env.COPILOT_API_KEY) {
copilotHeaders['x-api-key'] = env.COPILOT_API_KEY
}
const copilotRes = await fetchGo(`${SIM_AGENT_API_URL}/api/chats/fork`, {
method: 'POST',
headers: copilotHeaders,
body: JSON.stringify({
sourceChatId: chatId,
newChatId: newId,
upToMessageId,
keepCount: forkedMessages.length,
userId,
}),
Comment thread
waleedlatif1 marked this conversation as resolved.
Outdated
spanName: 'sim → go /api/chats/fork',
operation: 'fork_chat',
})
if (!copilotRes.ok) {
const text = await copilotRes.text().catch(() => '')
logger.warn('Copilot fork returned non-OK', { status: copilotRes.status, body: text })
logger.error('Copilot fork returned non-OK', { status: copilotRes.status, body: text })
copilotFailed = true
}
} catch (err) {
// The copilot service may not have a row for this chat if no messages
// have been sent yet, or if it's unreachable. Log and continue.
logger.warn('Failed to fork copilot-service conversation, skipping', { err })
logger.error('Failed to call copilot fork endpoint', { err })
copilotFailed = true
}

if (copilotFailed) {
// Compensating delete — remove the orphaned Sim row.
await db
.delete(copilotChats)
.where(eq(copilotChats.id, newId))
.catch((e: unknown) => {
logger.error('Failed to delete orphaned forked chat after copilot failure', {
error: e,
})
})
return createInternalServerErrorResponse('Failed to fork chat')
}

if (newChat.workspaceId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ interface MessageActionsProps {
userQuery?: string
requestId?: string
messageId?: string
isStreamActive?: boolean
}

export const MessageActions = memo(function MessageActions({
Expand All @@ -63,6 +64,7 @@ export const MessageActions = memo(function MessageActions({
userQuery,
requestId,
messageId,
isStreamActive,
}: MessageActionsProps) {
const router = useRouter()
const params = useParams<{ workspaceId: string }>()
Expand Down Expand Up @@ -164,7 +166,7 @@ export const MessageActions = memo(function MessageActions({

const hasContent = Boolean(content)
const canSubmitFeedback = Boolean(chatId && userQuery)
const canFork = false
const canFork = Boolean(messageId && !isStreamActive)
Comment thread
waleedlatif1 marked this conversation as resolved.
Outdated
Comment thread
waleedlatif1 marked this conversation as resolved.
Outdated
if (!hasContent && !canSubmitFeedback && !canFork) return null

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ export function MothershipChat({
userQuery={precedingUserContent}
requestId={msg.requestId}
messageId={msg.id}
isStreamActive={isStreamActive}
/>
</div>
)}
Expand Down
Loading