@@ -67,6 +67,86 @@ describe('moderation guardrail', () => {
6767 expect ( result . tripwireTriggered ) . toBe ( false ) ;
6868 expect ( result . info ?. error ) . toBe ( 'Moderation API call failed' ) ;
6969 } ) ;
70+
71+ it ( 'uses context client when available' , async ( ) => {
72+ // Track whether context client was used
73+ let contextClientUsed = false ;
74+ const contextCreateMock = vi . fn ( ) . mockImplementation ( async ( ) => {
75+ contextClientUsed = true ;
76+ return {
77+ results : [
78+ {
79+ categories : {
80+ [ Category . HATE ] : false ,
81+ [ Category . VIOLENCE ] : false ,
82+ } ,
83+ } ,
84+ ] ,
85+ } ;
86+ } ) ;
87+
88+ // Create a context with a guardrailLlm client
89+ // We need to import OpenAI to create a proper instance
90+ const OpenAI = ( await import ( 'openai' ) ) . default ;
91+ const contextClient = new OpenAI ( { apiKey : 'test-context-key' } ) ;
92+ contextClient . moderations = {
93+ create : contextCreateMock ,
94+ } as unknown as typeof contextClient . moderations ;
95+
96+ const ctx = { guardrailLlm : contextClient } ;
97+ const cfg = ModerationConfig . parse ( { categories : [ Category . HATE ] } ) ;
98+ const result = await moderationCheck ( ctx , 'test text' , cfg ) ;
99+
100+ // Verify the context client was used
101+ expect ( contextClientUsed ) . toBe ( true ) ;
102+ expect ( contextCreateMock ) . toHaveBeenCalledWith ( {
103+ model : 'omni-moderation-latest' ,
104+ input : 'test text' ,
105+ safety_identifier : 'openai-guardrails-js' ,
106+ } ) ;
107+ expect ( result . tripwireTriggered ) . toBe ( false ) ;
108+ } ) ;
109+
110+ it ( 'falls back to default client for third-party providers' , async ( ) => {
111+ // Track whether fallback client was used
112+ let fallbackUsed = false ;
113+
114+ // The default mock from vi.mock will be used for the fallback
115+ createMock . mockImplementation ( async ( ) => {
116+ fallbackUsed = true ;
117+ return {
118+ results : [
119+ {
120+ categories : {
121+ [ Category . HATE ] : false ,
122+ } ,
123+ } ,
124+ ] ,
125+ } ;
126+ } ) ;
127+
128+ // Create a context client that simulates a third-party provider
129+ // When moderation is called, it should raise a 404 error
130+ const contextCreateMock = vi . fn ( ) . mockRejectedValue ( {
131+ status : 404 ,
132+ message : '404 page not found' ,
133+ } ) ;
134+
135+ const OpenAI = ( await import ( 'openai' ) ) . default ;
136+ const thirdPartyClient = new OpenAI ( { apiKey : 'third-party-key' , baseURL : 'https://localhost:8080/v1' } ) ;
137+ thirdPartyClient . moderations = {
138+ create : contextCreateMock ,
139+ } as unknown as typeof thirdPartyClient . moderations ;
140+
141+ const ctx = { guardrailLlm : thirdPartyClient } ;
142+ const cfg = ModerationConfig . parse ( { categories : [ Category . HATE ] } ) ;
143+ const result = await moderationCheck ( ctx , 'test text' , cfg ) ;
144+
145+ // Verify the fallback client was used (not the third-party one)
146+ expect ( contextCreateMock ) . toHaveBeenCalled ( ) ;
147+ expect ( fallbackUsed ) . toBe ( true ) ;
148+ expect ( result . tripwireTriggered ) . toBe ( false ) ;
149+ } ) ;
70150} ) ;
71151
72152describe ( 'secret key guardrail' , ( ) => {
0 commit comments