diff --git a/plugins/javelin/guardrails.ts b/plugins/highflame/guardrails.ts similarity index 63% rename from plugins/javelin/guardrails.ts rename to plugins/highflame/guardrails.ts index 1216fa7e4..5499419a0 100644 --- a/plugins/javelin/guardrails.ts +++ b/plugins/highflame/guardrails.ts @@ -6,12 +6,17 @@ import { } from '../types'; import { getCurrentContentPart } from '../utils'; -interface JavelinCredentials { +interface HighflameCredentials { apiKey: string; domain?: string; application?: string; } +interface GuardrailConfig { + name: string; + config?: Record; +} + interface GuardrailAssessment { [key: string]: { categories?: Record; @@ -34,35 +39,51 @@ interface GuardrailsResponse { assessments: Array; } -async function callJavelinGuardrails( +// Default guardrails to run if none specified +const DEFAULT_GUARDRAILS: GuardrailConfig[] = [ + { name: 'trustsafety', config: { threshold: 0.75 } }, + { name: 'promptinjectiondetection', config: { threshold: 0.8 } }, +]; + +async function callHighflameGuardrails( text: string, - credentials: JavelinCredentials + credentials: HighflameCredentials, + guardrails?: GuardrailConfig[], + globalThreshold?: number ): Promise { // Strip https:// or http:// from domain if present - let domain = credentials.domain || 'api-dev.javelin.live'; + let domain = credentials.domain || 'api-dev.highflame.dev'; domain = domain.replace(/^https?:\/\//, ''); const apiUrl = `https://${domain}/v1/guardrails/apply`; - console.log('[Javelin] Calling API:', apiUrl); - console.log('[Javelin] Application:', credentials.application); + console.log('[Highflame] Calling API:', apiUrl); + console.log('[Highflame] Application:', credentials.application); const headers: Record = { 'Content-Type': 'application/json', - 'x-javelin-apikey': credentials.apiKey, + 'x-highflame-apikey': credentials.apiKey, }; if (credentials.application) { - headers['x-javelin-application'] = credentials.application; + headers['x-highflame-application'] = credentials.application; } - const requestBody = { + // Use provided guardrails or defaults + const guardrailsToRun = + guardrails && guardrails.length > 0 ? guardrails : DEFAULT_GUARDRAILS; + + const requestBody: Record = { input: { text }, - config: {}, - metadata: {}, + guardrails: guardrailsToRun, }; - console.log('[Javelin] Request body:', JSON.stringify(requestBody)); + // Add global config if threshold specified + if (globalThreshold !== undefined) { + requestBody.config = { threshold: globalThreshold }; + } + + console.log('[Highflame] Request body:', JSON.stringify(requestBody)); const response = await fetch(apiUrl, { method: 'POST', @@ -70,13 +91,13 @@ async function callJavelinGuardrails( body: JSON.stringify(requestBody), }); - console.log('[Javelin] Response status:', response.status); + console.log('[Highflame] Response status:', response.status); if (!response.ok) { const errorText = await response.text(); - console.error('[Javelin] API error:', errorText); + console.error('[Highflame] API error:', errorText); throw new Error( - `Javelin Guardrails API error: ${response.status} ${response.statusText} - ${errorText}` + `Highflame Guardrails API error: ${response.status} ${response.statusText} - ${errorText}` ); } @@ -90,28 +111,28 @@ export const handler: PluginHandler = async ( parameters: PluginParameters, eventType: HookEventType ) => { - console.log('[Javelin] Handler called with eventType:', eventType); + console.log('[Highflame] Handler called with eventType:', eventType); console.log( - '[Javelin] Full parameters object:', + '[Highflame] Full parameters object:', JSON.stringify(parameters, null, 2) ); - console.log('[Javelin] Parameters keys:', Object.keys(parameters)); + console.log('[Highflame] Parameters keys:', Object.keys(parameters)); let error = null; let verdict = true; let data = null; // Try multiple ways to get credentials - let credentials = parameters.credentials as unknown as JavelinCredentials; + let credentials = parameters.credentials as unknown as HighflameCredentials; // If credentials not at root, check if they're nested or direct properties if (!credentials || !credentials.apiKey) { - console.log('[Javelin] Credentials not found at parameters.credentials'); - console.log('[Javelin] Trying direct properties...'); + console.log('[Highflame] Credentials not found at parameters.credentials'); + console.log('[Highflame] Trying direct properties...'); // Check if credentials are passed as direct properties if (parameters.apiKey) { - console.log('[Javelin] Found credentials as direct properties'); + console.log('[Highflame] Found credentials as direct properties'); credentials = { apiKey: parameters.apiKey as string, domain: parameters.domain as string | undefined, @@ -120,7 +141,7 @@ export const handler: PluginHandler = async ( } } - console.log('[Javelin] Final credentials check:', { + console.log('[Highflame] Final credentials check:', { hasApiKey: !!credentials?.apiKey, hasDomain: !!credentials?.domain, hasApplication: !!credentials?.application, @@ -130,7 +151,7 @@ export const handler: PluginHandler = async ( }); if (!credentials?.apiKey) { - console.error('[Javelin] Missing API key after all checks'); + console.error('[Highflame] Missing API key after all checks'); return { error: `'parameters.credentials.apiKey' must be set. Received parameters keys: ${Object.keys(parameters).join(', ')}`, verdict: true, @@ -139,7 +160,7 @@ export const handler: PluginHandler = async ( } if (!credentials?.application) { - console.error('[Javelin] Missing application name'); + console.error('[Highflame] Missing application name'); return { error: `'parameters.credentials.application' must be set. Received: ${JSON.stringify(credentials)}`, verdict: true, @@ -149,7 +170,7 @@ export const handler: PluginHandler = async ( const { content, textArray } = getCurrentContentPart(context, eventType); if (!content) { - console.error('[Javelin] No content to check'); + console.error('[Highflame] No content to check'); return { error: { message: 'request or response json is empty' }, verdict: true, @@ -158,18 +179,27 @@ export const handler: PluginHandler = async ( } const text = textArray.filter((text) => text).join('\n'); - console.log('[Javelin] Text to check (length):', text.length); + console.log('[Highflame] Text to check (length):', text.length); + + // Get optional guardrails config from parameters + const guardrails = parameters.guardrails as GuardrailConfig[] | undefined; + const threshold = parameters.threshold as number | undefined; try { - const response = await callJavelinGuardrails(text, credentials); + const response = await callHighflameGuardrails( + text, + credentials, + guardrails, + threshold + ); const assessments = response.assessments || []; - console.log('[Javelin] Received', assessments.length, 'assessments'); + console.log('[Highflame] Received', assessments.length, 'assessments'); if (assessments.length === 0) { - console.warn('[Javelin] No assessments in response'); + console.warn('[Highflame] No assessments in response'); return { - error: { message: 'No assessments in Javelin response' }, + error: { message: 'No assessments in Highflame response' }, verdict: true, data: null, }; @@ -191,7 +221,7 @@ export const handler: PluginHandler = async ( assessment )) { console.log( - '[Javelin] Assessment:', + '[Highflame] Assessment:', assessmentType, 'request_reject:', assessmentData.request_reject @@ -223,10 +253,10 @@ export const handler: PluginHandler = async ( // Use a default message if no reject_prompt was found if (!rejectPrompt) { rejectPrompt = - 'Request blocked by Javelin guardrails due to policy violation'; + 'Request blocked by Highflame guardrails due to policy violation'; } - console.log('[Javelin] Request REJECTED:', rejectPrompt); + console.log('[Highflame] Request REJECTED:', rejectPrompt); // Return with verdict false and NO error field for policy violations // Portkey will handle the deny logic based on guardrail actions @@ -235,10 +265,10 @@ export const handler: PluginHandler = async ( data = { flagged_assessments: flaggedAssessments, reject_prompt: rejectPrompt, - javelin_response: response, + highflame_response: response, }; } else { - console.log('[Javelin] Request PASSED all guardrails'); + console.log('[Highflame] Request PASSED all guardrails'); // All guardrails passed verdict = true; @@ -250,12 +280,12 @@ export const handler: PluginHandler = async ( } } catch (e: any) { // Handle API errors - still return verdict true so Portkey doesn't block - console.error('[Javelin] Error calling API:', e.message); - console.error('[Javelin] Error details:', e); + console.error('[Highflame] Error calling API:', e.message); + console.error('[Highflame] Error details:', e); // Create a serializable error object error = { - message: e.message || 'Unknown error calling Javelin API', + message: e.message || 'Unknown error calling Highflame API', name: e.name, ...(e.cause && { cause: e.cause }), }; @@ -266,7 +296,7 @@ export const handler: PluginHandler = async ( }; } - console.log('[Javelin] Returning:', { + console.log('[Highflame] Returning:', { verdict, hasError: !!error, hasData: !!data, diff --git a/plugins/javelin/javelin.test.ts b/plugins/highflame/highflame.test.ts similarity index 98% rename from plugins/javelin/javelin.test.ts rename to plugins/highflame/highflame.test.ts index a36cb8dea..b1ea932ca 100644 --- a/plugins/javelin/javelin.test.ts +++ b/plugins/highflame/highflame.test.ts @@ -2,7 +2,7 @@ global.fetch = jest.fn(); import { handler as guardrailsHandler } from './guardrails'; -describe('Javelin Guardrails Tests', () => { +describe('Highflame Guardrails Tests', () => { beforeEach(() => { jest.clearAllMocks(); }); @@ -159,7 +159,7 @@ describe('Javelin Guardrails Tests', () => { expect(result.data.reject_prompt).toBe( 'Unable to complete request, trust & safety violation detected' ); - expect(result.data.javelin_response).toEqual(mockResponse); + expect(result.data.highflame_response).toEqual(mockResponse); expect(result.data.flagged_assessments).toHaveLength(1); expect(result.data.flagged_assessments[0].type).toBe('trustsafety'); expect(result.data.flagged_assessments[0].request_reject).toBe(true); @@ -424,7 +424,7 @@ describe('Javelin Guardrails Tests', () => { expect(result.verdict).toBe(false); expect(result.error).toBe( - 'Request blocked by Javelin guardrails due to policy violation' + 'Request blocked by Highflame guardrails due to policy violation' ); }); diff --git a/plugins/highflame/manifest.json b/plugins/highflame/manifest.json new file mode 100644 index 000000000..a779a59db --- /dev/null +++ b/plugins/highflame/manifest.json @@ -0,0 +1,92 @@ +{ + "id": "highflame", + "description": "Highflame's AI security platform provides comprehensive guardrails for trust & safety, prompt injection detection, and language detection. Applies all enabled guardrails configured in your Highflame application policy. Learn more at https://docs.highflame.ai/", + "credentials": { + "type": "object", + "properties": { + "apiKey": { + "type": "string", + "label": "API Key", + "description": [ + { + "type": "subHeading", + "text": "Your Highflame API key for authentication" + } + ] + }, + "domain": { + "type": "string", + "label": "Domain", + "description": [ + { + "type": "subHeading", + "text": "Highflame API domain" + } + ], + "default": "api-dev.highflame.dev", + "required": false + }, + "application": { + "type": "string", + "label": "Application Name", + "description": [ + { + "type": "subHeading", + "text": "Application name for policy-specific guardrails (required). See https://docs.highflame.ai/documentation/agent-control-fabric/guardrails-policies/guardrail-apis" + } + ], + "required": true + } + }, + "required": ["apiKey", "application"] + }, + "functions": [ + { + "name": "Highflame Guardrails", + "id": "guardrails", + "supportedHooks": ["beforeRequestHook", "afterRequestHook"], + "type": "guardrail", + "description": [ + { + "type": "subHeading", + "text": "Auto-applies all enabled guardrails in your Highflame application policy including trust & safety, prompt injection detection, language detection, and more" + } + ], + "parameters": { + "type": "object", + "properties": { + "guardrails": { + "type": "array", + "description": "List of guardrails to run. Defaults to trustsafety and promptinjectiondetection if not specified.", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "enum": [ + "trustsafety", + "promptinjectiondetection", + "lang_detector", + "dlp_gcp", + "model_armor" + ] + }, + "config": { + "type": "object", + "properties": { + "threshold": { "type": "number" } + } + } + }, + "required": ["name"] + } + }, + "threshold": { + "type": "number", + "description": "Global threshold for all guardrails (0-1). Can be overridden per guardrail." + } + } + } + } + ] +} diff --git a/plugins/index.ts b/plugins/index.ts index 641738b50..cb1cdd13b 100644 --- a/plugins/index.ts +++ b/plugins/index.ts @@ -62,118 +62,13 @@ import { handler as defaultrequiredMetadataKeys } from './default/requiredMetada import { handler as walledaiguardrails } from './walledai/walledprotect'; import { handler as defaultregexReplace } from './default/regexReplace'; import { handler as defaultallowedRequestTypes } from './default/allowedRequestTypes'; -import { handler as javelinguardrails } from './javelin/guardrails'; +import { handler as highflameguardrails } from './highflame/guardrails'; import { handler as f5GuardrailsScan } from './f5-guardrails/scan'; import { handler as azureShieldPrompt } from './azure/shieldPrompt'; import { handler as azureProtectedMaterial } from './azure/protectedMaterial'; export const plugins = { - default: { - regexMatch: defaultregexMatch, - sentenceCount: defaultsentenceCount, - wordCount: defaultwordCount, - characterCount: defaultcharacterCount, - jsonSchema: defaultjsonSchema, - jsonKeys: defaultjsonKeys, - contains: defaultcontains, - validUrls: defaultvalidUrls, - webhook: defaultwebhook, - log: defaultlog, - containsCode: defaultcontainsCode, - alluppercase: defaultalluppercase, - alllowercase: defaultalllowercase, - endsWith: defaultendsWith, - modelWhitelist: defaultmodelWhitelist, - modelRules: defaultmodelRules, - jwt: defaultjwt, - requiredMetadataKeys: defaultrequiredMetadataKeys, - addPrefix: defaultaddPrefix, - regexReplace: defaultregexReplace, - allowedRequestTypes: defaultallowedRequestTypes, - notNull: defaultnotNull, - }, - qualifire: { - contentModeration: qualifireContentModeration, - grounding: qualifireGrounding, - policy: qualifirePolicy, - toolUseQuality: qualifireToolUseQuality, - hallucinations: qualifireHallucinations, - pii: qualifirePii, - promptInjections: qualifirePromptInjections, - }, - portkey: { - moderateContent: portkeymoderateContent, - language: portkeylanguage, - pii: portkeypii, - gibberish: portkeygibberish, - }, - aporia: { - validateProject: aporiavalidateProject, - }, - sydelabs: { - sydeguard: sydelabssydeguard, - }, - pillar: { - scanPrompt: pillarscanPrompt, - scanResponse: pillarscanResponse, - }, - patronus: { - phi: patronusphi, - pii: patronuspii, - isConcise: patronusisConcise, - isHelpful: patronusisHelpful, - isPolite: patronusisPolite, - noApologies: patronusnoApologies, - noGenderBias: patronusnoGenderBias, - noRacialBias: patronusnoRacialBias, - retrievalAnswerRelevance: patronusretrievalAnswerRelevance, - toxicity: patronustoxicity, - custom: patronuscustom, - }, - mistral: { - moderateContent: mistralGuardrailHandler, - }, - pangea: { - textGuard: pangeatextGuard, - pii: pangeapii, - }, - promptfoo: { - pii: promptfooPii, - harm: promptfooHarm, - guard: promptfooGuard, - }, - bedrock: { - guard: bedrockHandler, - }, - acuvity: { - scan: acuvityScan, - }, - lasso: { - classify: lassoclassify, - }, - exa: { - online: exaonline, - }, - azure: { - pii: azurePii, - contentSafety: azureContentSafety, - shieldPrompt: azureShieldPrompt, - protectedMaterial: azureProtectedMaterial, - }, - promptsecurity: { - protectPrompt: promptSecurityProtectPrompt, - protectResponse: promptSecurityProtectResponse, - }, - 'panw-prisma-airs': { - intercept: panwPrismaAirsintercept, - }, - walledai: { - walledprotect: walledaiguardrails, - }, - javelin: { - guardrails: javelinguardrails, - }, - 'f5-guardrails': { - scan: f5GuardrailsScan, + highflame: { + guardrails: highflameguardrails, }, }; diff --git a/plugins/javelin/manifest.json b/plugins/javelin/manifest.json deleted file mode 100644 index 0bd5f4746..000000000 --- a/plugins/javelin/manifest.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "id": "javelin", - "description": "Javelin's AI security platform provides comprehensive guardrails for trust & safety, prompt injection detection, and language detection. Applies all enabled guardrails configured in your Javelin application policy.", - "credentials": { - "type": "object", - "properties": { - "apiKey": { - "type": "string", - "label": "API Key", - "description": [ - { - "type": "subHeading", - "text": "Your Javelin API key for authentication" - } - ] - }, - "domain": { - "type": "string", - "label": "Domain", - "description": [ - { - "type": "subHeading", - "text": "Javelin API domain" - } - ], - "default": "api-dev.javelin.live", - "required": false - }, - "application": { - "type": "string", - "label": "Application Name", - "description": [ - { - "type": "subHeading", - "text": "Application name for policy-specific guardrails (required)" - } - ], - "required": true - } - }, - "required": ["apiKey", "application"] - }, - "functions": [ - { - "name": "Javelin Guardrails", - "id": "guardrails", - "supportedHooks": ["beforeRequestHook", "afterRequestHook"], - "type": "guardrail", - "description": [ - { - "type": "subHeading", - "text": "Auto-applies all enabled guardrails in your Javelin application policy including trust & safety, prompt injection detection, language detection, and more" - } - ], - "parameters": { - "type": "object", - "properties": {} - } - } - ] -}