MCPcopy Index your code
hub / github.com/simstudioai/sim / handleUnifiedChatPost

Function handleUnifiedChatPost

apps/sim/lib/copilot/chat/post.ts:699–1116  ·  view source on GitHub ↗
(req: NextRequest)

Source from the content-addressed store, hash-verified

697}
698
699export async function handleUnifiedChatPost(req: NextRequest) {
700 let actualChatId: string | undefined
701 let userMessageId = ''
702 let chatStreamLockAcquired = false
703 // Started once we've parsed the body (need userMessageId to stamp as
704 // streamId). Every subsequent span (persistUserMessage,
705 // createRunSegment, the whole SSE stream, etc.) nests under this
706 // root via AsyncLocalStorage / explicit propagation, and the stream's
707 // terminal code path calls finish() when the request actually ends.
708 // Errors thrown from the handler before the stream starts are
709 // finished here in the catch below.
710 let otelRoot: ReturnType<typeof startCopilotOtelRoot> | undefined
711 // Canonical logical ID; assigned from otelRoot.requestId (the OTel
712 // trace ID) as soon as startCopilotOtelRoot runs. Empty only in the
713 // narrow pre-otelRoot window where errors don't correlate anyway.
714 let requestId = ''
715 const executionId = generateId()
716 const runId = generateId()
717
718 try {
719 const session = await getSession()
720 if (!session?.user?.id) {
721 return createUnauthorizedResponse()
722 }
723 const authenticatedUserId = session.user.id
724 const authenticatedUserEmail = session.user.email
725 const authenticatedUserName =
726 typeof session.user.name === 'string' ? session.user.name : undefined
727
728 const body = ChatMessageSchema.parse(await req.json())
729 const userMetadata = {
730 ...(authenticatedUserName ? { name: authenticatedUserName } : {}),
731 ...(authenticatedUserEmail ? { email: authenticatedUserEmail } : {}),
732 ...(body.userTimezone ? { timezone: body.userTimezone } : {}),
733 }
734 const normalizedContexts = normalizeContexts(body.contexts) ?? []
735 userMessageId = body.userMessageId || generateId()
736
737 otelRoot = startCopilotOtelRoot({
738 streamId: userMessageId,
739 executionId,
740 runId,
741 transport: CopilotTransport.Stream,
742 userMessagePreview: body.message,
743 })
744 if (otelRoot.requestId) {
745 requestId = otelRoot.requestId
746 }
747 // Identity stamp — Go already stamps `user.id` on spans from the
748 // validated API-key path, but Sim is the only side of the wire
749 // that knows the human-facing email. Stamping both on the Sim
750 // root (so they show up on `rootAttrs` in Tempo search) saves
751 // the "turn user.id into a real person" round-trip to the DB
752 // for every ad-hoc investigation.
753 otelRoot.span.setAttribute(TraceAttr.UserId, authenticatedUserId)
754 if (authenticatedUserEmail) {
755 otelRoot.span.setAttribute(TraceAttr.UserEmail, authenticatedUserEmail)
756 }

Callers 2

post.test.tsFile · 0.90
route.tsFile · 0.90

Calls 15

generateIdFunction · 0.90
startCopilotOtelRootFunction · 0.90
withCopilotSpanFunction · 0.90
resolveOrCreateChatFunction · 0.90
persistChatResourcesFunction · 0.90
acquirePendingChatStreamFunction · 0.90
getPendingChatStreamIdFunction · 0.90
getUserEntityPermissionsFunction · 0.90
getErrorMessageFunction · 0.90
createSSEStreamFunction · 0.90

Tested by

no test coverage detected