11import { beforeEach , describe , expect , test , vi } from 'vitest' ;
2+ import type { UserWithAccounts } from '@sourcebot/db' ;
3+ import { runWithCurrentUser } from '@/lib/currentUserContext' ;
24
35const mocks = vi . hoisted ( ( ) => ( {
46 env : {
@@ -15,37 +17,54 @@ import {
1517 SOURCEBOT_USER_EMAIL_HEADER ,
1618} from './languageModelHeaders.server' ;
1719
20+ const resolveHeadersForUser = (
21+ email : string ,
22+ configuredHeaders ?: Parameters < typeof resolveLanguageModelHeaders > [ 0 ] ,
23+ ) =>
24+ runWithCurrentUser (
25+ { email } as unknown as UserWithAccounts ,
26+ ( ) => resolveLanguageModelHeaders ( configuredHeaders ) ,
27+ ) ;
28+
1829describe ( 'resolveLanguageModelHeaders' , ( ) => {
1930 beforeEach ( ( ) => {
2031 mocks . env . SOURCEBOT_LLM_USER_EMAIL_HEADER_ENABLED = 'false' ;
2132 mocks . getTokenFromConfig . mockReset ( ) ;
2233 } ) ;
2334
2435 test ( 'does not add the user email header by default' , async ( ) => {
25- await expect ( resolveLanguageModelHeaders ( undefined , 'User@Example.com' ) ) . resolves . toBeUndefined ( ) ;
36+ await expect ( resolveHeadersForUser ( 'User@Example.com' ) ) . resolves . toBeUndefined ( ) ;
2637 } ) ;
2738
28- test ( 'adds a lower-cased user email when enabled' , async ( ) => {
39+ test ( 'adds the current user email in lower case when enabled' , async ( ) => {
2940 mocks . env . SOURCEBOT_LLM_USER_EMAIL_HEADER_ENABLED = 'true' ;
3041
31- await expect ( resolveLanguageModelHeaders ( undefined , 'User@Example.COM' ) ) . resolves . toEqual ( {
42+ await expect ( resolveHeadersForUser ( 'User@Example.COM' ) ) . resolves . toEqual ( {
3243 [ SOURCEBOT_USER_EMAIL_HEADER ] : 'user@example.com' ,
3344 } ) ;
3445 } ) ;
3546
3647 test ( 'omits the user email header for anonymous requests' , async ( ) => {
3748 mocks . env . SOURCEBOT_LLM_USER_EMAIL_HEADER_ENABLED = 'true' ;
3849
39- await expect ( resolveLanguageModelHeaders ( undefined , undefined ) ) . resolves . toBeUndefined ( ) ;
50+ await expect ( resolveLanguageModelHeaders ( undefined ) ) . resolves . toBeUndefined ( ) ;
51+ } ) ;
52+
53+ test ( 'omits synthetic placeholder emails' , async ( ) => {
54+ mocks . env . SOURCEBOT_LLM_USER_EMAIL_HEADER_ENABLED = 'true' ;
55+
56+ await expect ( resolveHeadersForUser (
57+ 'placeholder-internal-user-id@no-email.invalid' ,
58+ ) ) . resolves . toBeUndefined ( ) ;
4059 } ) ;
4160
4261 test ( 'preserves configured headers and overrides a case-insensitive email header' , async ( ) => {
4362 mocks . env . SOURCEBOT_LLM_USER_EMAIL_HEADER_ENABLED = 'true' ;
4463
45- await expect ( resolveLanguageModelHeaders ( {
64+ await expect ( resolveHeadersForUser ( 'Authenticated@Example.com' , {
4665 'x-sourcebot-user-email' : 'configured@example.com' ,
4766 'X-Custom-Header' : 'custom-value' ,
48- } , 'Authenticated@Example.com' ) ) . resolves . toEqual ( {
67+ } ) ) . resolves . toEqual ( {
4968 'X-Custom-Header' : 'custom-value' ,
5069 [ SOURCEBOT_USER_EMAIL_HEADER ] : 'authenticated@example.com' ,
5170 } ) ;
@@ -55,7 +74,7 @@ describe('resolveLanguageModelHeaders', () => {
5574 const token = { env : 'CUSTOM_HEADER' } ;
5675 mocks . getTokenFromConfig . mockResolvedValue ( 'resolved-value' ) ;
5776
58- await expect ( resolveLanguageModelHeaders ( { Authorization : token } , undefined ) ) . resolves . toEqual ( {
77+ await expect ( resolveLanguageModelHeaders ( { Authorization : token } ) ) . resolves . toEqual ( {
5978 Authorization : 'resolved-value' ,
6079 } ) ;
6180 expect ( mocks . getTokenFromConfig ) . toHaveBeenCalledWith ( token ) ;
0 commit comments