From 536cd6a5d1626cb7af3558dcebde6b019818890b Mon Sep 17 00:00:00 2001 From: Huarch Date: Mon, 11 May 2026 16:37:55 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8E=B7=E5=8F=96=E7=94=A8?= =?UTF-8?q?=E6=88=B7=20ID=20=E7=9A=84=E5=8A=9F=E8=83=BD=EF=BC=8CAgent=20ch?= =?UTF-8?q?at=20=E8=AF=B7=E6=B1=82=E5=A4=B4=E6=96=B0=E5=A2=9E=E4=BC=A0?= =?UTF-8?q?=E9=80=92=20userId?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/authToken.ts | 27 +++++++++++++++++++++++++++ src/lib/chatStream.ts | 3 +++ src/lib/requestHeaders.ts | 11 ++++++++++- 3 files changed, 40 insertions(+), 1 deletion(-) 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 &&