diff --git a/src/lib/authToken.ts b/src/lib/authToken.ts index ee0f15c..72bbff5 100644 --- a/src/lib/authToken.ts +++ b/src/lib/authToken.ts @@ -49,3 +49,30 @@ export const getAccessToken = async () => { } return null; }; + +export const getUserId = async () => { + const session = await getSession(); + const sessionUserId = typeof session?.user?.id === "string" ? session.user.id : null; + if (sessionUserId) { + return sessionUserId; + } + + const accessToken = await getAccessToken(); + if (!accessToken) { + return null; + } + + const payload = decodeJwtPayload(accessToken); + if (!payload || typeof payload !== "object") { + return null; + } + + const candidate = + typeof payload.sub === "string" + ? payload.sub + : typeof payload.user_id === "string" + ? payload.user_id + : null; + + return candidate; +}; diff --git a/src/lib/chatStream.ts b/src/lib/chatStream.ts index f32a61b..2da5472 100644 --- a/src/lib/chatStream.ts +++ b/src/lib/chatStream.ts @@ -99,6 +99,7 @@ export const streamAgentChat = async ({ session_id: sessionId, }), projectHeaderMode: "include", + userHeaderMode: "include", skipAuthRedirect: true, }, ); @@ -229,6 +230,7 @@ export const abortAgentChat = async (sessionId?: string) => { session_id: sessionId, }), projectHeaderMode: "include", + userHeaderMode: "include", skipAuthRedirect: true, }); @@ -249,6 +251,7 @@ export const forkAgentChat = async (sessionId: string | undefined, keepMessageCo keep_message_count: keepMessageCount, }), projectHeaderMode: "include", + userHeaderMode: "include", skipAuthRedirect: true, }); diff --git a/src/lib/requestHeaders.ts b/src/lib/requestHeaders.ts index 95e45ac..541ce4d 100644 --- a/src/lib/requestHeaders.ts +++ b/src/lib/requestHeaders.ts @@ -1,12 +1,14 @@ -import { getAccessToken } from "@/lib/authToken"; +import { getAccessToken, getUserId } from "@/lib/authToken"; import { useProjectStore } from "@/store/projectStore"; export type AuthHeaderMode = "include" | "omit"; export type ProjectHeaderMode = "auto" | "include" | "omit"; +export type UserHeaderMode = "include" | "omit"; export interface AuthContextHeaderOptions { authHeaderMode?: AuthHeaderMode; projectHeaderMode?: ProjectHeaderMode; + userHeaderMode?: UserHeaderMode; } const shouldIncludeProjectHeader = ( @@ -34,6 +36,13 @@ export const applyAuthContextHeaders = async ( headers.set("Authorization", `Bearer ${accessToken}`); } + if (options.userHeaderMode === "include") { + const userId = await getUserId(); + if (userId) { + headers.set("X-User-Id", userId); + } + } + const projectId = useProjectStore.getState().currentProjectId; if ( projectId &&