From eda6861b089b1682c6861b8d2e5fa218fa8a427a Mon Sep 17 00:00:00 2001 From: Steven C Date: Mon, 3 Nov 2025 11:58:52 -0500 Subject: [PATCH 1/4] Properly pass back execution errors --- .../checks/moderation-secret-keys.test.ts | 18 +++++++- src/checks/moderation.ts | 45 +++++++++++-------- 2 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/__tests__/unit/checks/moderation-secret-keys.test.ts b/src/__tests__/unit/checks/moderation-secret-keys.test.ts index 96c575b..934caa1 100644 --- a/src/__tests__/unit/checks/moderation-secret-keys.test.ts +++ b/src/__tests__/unit/checks/moderation-secret-keys.test.ts @@ -65,7 +65,23 @@ describe('moderation guardrail', () => { const result = await moderationCheck({}, 'safe text', ModerationConfig.parse({})); expect(result.tripwireTriggered).toBe(false); - expect(result.info?.error).toBe('Moderation API call failed'); + expect(result.executionFailed).toBe(true); + expect(result.originalException).toBeDefined(); + expect(result.info?.error).toContain('network down'); + }); + + it('returns executionFailed for API key errors to support raiseGuardrailErrors', async () => { + const apiKeyError = new Error( + 'Incorrect API key provided: sk-invalid. You can find your API key at https://platform.openai.com/account/api-keys.' + ); + createMock.mockRejectedValue(apiKeyError); + + const result = await moderationCheck({}, 'test text', ModerationConfig.parse({})); + + expect(result.tripwireTriggered).toBe(false); + expect(result.executionFailed).toBe(true); + expect(result.originalException).toBe(apiKeyError); + expect(result.info?.error).toContain('Incorrect API key'); }); it('uses context client when available', async () => { diff --git a/src/checks/moderation.ts b/src/checks/moderation.ts index 00661ca..550a695 100644 --- a/src/checks/moderation.ts +++ b/src/checks/moderation.ts @@ -162,25 +162,32 @@ export const moderationCheck: CheckFn Date: Mon, 3 Nov 2025 12:21:39 -0500 Subject: [PATCH 2/4] Remove unneeded OAI check --- src/checks/moderation.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/checks/moderation.ts b/src/checks/moderation.ts index 550a695..dc567fc 100644 --- a/src/checks/moderation.ts +++ b/src/checks/moderation.ts @@ -144,8 +144,9 @@ export const moderationCheck: CheckFn; const candidate = contextObj.guardrailLlm; - if (candidate && candidate instanceof OpenAI) { - client = candidate; + // Just use whatever is provided, let the try-catch handle validation + if (candidate) { + client = candidate as OpenAI; } } From f085faa3789d9a46ab5ba08794f7903a3d6cf7c9 Mon Sep 17 00:00:00 2001 From: Steven C Date: Mon, 3 Nov 2025 15:10:27 -0500 Subject: [PATCH 3/4] Extract error helper --- src/checks/moderation.ts | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/checks/moderation.ts b/src/checks/moderation.ts index dc567fc..8cc7863 100644 --- a/src/checks/moderation.ts +++ b/src/checks/moderation.ts @@ -89,6 +89,17 @@ function isNotFoundError(error: unknown): boolean { return !!(error && typeof error === 'object' && 'status' in error && error.status === 404); } +/** + * Ensure a value is an Error instance. + * Converts non-Error values to Error instances with a string representation. + * + * @param error The error value to convert + * @returns An Error instance + */ +function ensureError(error: unknown): Error { + return error instanceof Error ? error : new Error(String(error)); +} + /** * Call the OpenAI moderation API. * @@ -168,12 +179,10 @@ export const moderationCheck: CheckFn Date: Tue, 4 Nov 2025 10:39:02 -0500 Subject: [PATCH 4/4] Copilot comments --- src/checks/moderation.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/checks/moderation.ts b/src/checks/moderation.ts index 8cc7863..f413f98 100644 --- a/src/checks/moderation.ts +++ b/src/checks/moderation.ts @@ -176,26 +176,28 @@ export const moderationCheck: CheckFn