@@ -89,6 +89,17 @@ function isNotFoundError(error: unknown): boolean {
8989 return ! ! ( error && typeof error === 'object' && 'status' in error && error . status === 404 ) ;
9090}
9191
92+ /**
93+ * Ensure a value is an Error instance.
94+ * Converts non-Error values to Error instances with a string representation.
95+ *
96+ * @param error The error value to convert
97+ * @returns An Error instance
98+ */
99+ function ensureError ( error : unknown ) : Error {
100+ return error instanceof Error ? error : new Error ( String ( error ) ) ;
101+ }
102+
92103/**
93104 * Call the OpenAI moderation API.
94105 *
@@ -144,8 +155,9 @@ export const moderationCheck: CheckFn<ModerationContext, string, ModerationConfi
144155 if ( ctx ) {
145156 const contextObj = ctx as Record < string , unknown > ;
146157 const candidate = contextObj . guardrailLlm ;
147- if ( candidate && candidate instanceof OpenAI ) {
148- client = candidate ;
158+ // Just use whatever is provided, let the try-catch handle validation
159+ if ( candidate ) {
160+ client = candidate as OpenAI ;
149161 }
150162 }
151163
@@ -162,25 +174,32 @@ export const moderationCheck: CheckFn<ModerationContext, string, ModerationConfi
162174 try {
163175 resp = await callModerationAPI ( new OpenAI ( ) , data ) ;
164176 } catch ( fallbackError ) {
165- // If fallback fails, provide a helpful error message
166- const errorMessage = fallbackError instanceof Error
167- ? fallbackError . message
168- : String ( fallbackError ) ;
169-
170- // Check if it's an API key error
171- if ( errorMessage . includes ( 'api_key' ) || errorMessage . includes ( 'OPENAI_API_KEY' ) ) {
172- return {
173- tripwireTriggered : false ,
174- info : {
175- checked_text : data ,
176- error : 'Moderation API requires OpenAI API key. Set OPENAI_API_KEY environment variable or pass a client with valid credentials.' ,
177- } ,
178- } ;
179- }
180- throw fallbackError ;
177+ // If fallback fails, return execution failure
178+ // This allows runGuardrails to handle based on raiseGuardrailErrors flag
179+ const errorObj = ensureError ( fallbackError ) ;
180+ return {
181+ tripwireTriggered : false ,
182+ executionFailed : true ,
183+ originalException : errorObj ,
184+ info : {
185+ checked_text : data ,
186+ error : errorObj . message ,
187+ } ,
188+ } ;
181189 }
182190 } else {
183- throw error ;
191+ // Non-404 error from context client - return execution failure
192+ // This allows runGuardrails to handle based on raiseGuardrailErrors flag
193+ const errorObj = ensureError ( error ) ;
194+ return {
195+ tripwireTriggered : false ,
196+ executionFailed : true ,
197+ originalException : errorObj ,
198+ info : {
199+ checked_text : data ,
200+ error : errorObj . message ,
201+ } ,
202+ } ;
184203 }
185204 }
186205 } else {
@@ -230,11 +249,14 @@ export const moderationCheck: CheckFn<ModerationContext, string, ModerationConfi
230249 } ;
231250 } catch ( error ) {
232251 console . warn ( 'AI-based moderation failed:' , error ) ;
252+ const errorObj = ensureError ( error ) ;
233253 return {
234254 tripwireTriggered : false ,
255+ executionFailed : true ,
256+ originalException : errorObj ,
235257 info : {
236258 checked_text : data ,
237- error : 'Moderation API call failed' ,
259+ error : errorObj . message ,
238260 } ,
239261 } ;
240262 }
0 commit comments