first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 21:52:23 +03:00
commit 880f412e2c
2662 changed files with 866266 additions and 0 deletions

View File

@@ -0,0 +1,195 @@
/**
* CEL Fields Configuration for Routing Rules
* Defines available fields for building routing rule expressions
*/
import { getProviderLabel } from "@/lib/constants/logs";
export interface CELFieldDefinition {
name: string;
label: string;
placeholder?: string;
inputType?: "text" | "select" | "keyValue" | "number";
valueEditorType?:
| "text"
| "select"
| "keyValue"
| "number"
| "textarea"
| "budgetNumber"
| ((operator: string) => "text" | "select" | "keyValue" | "number" | "textarea" | "budgetNumber");
operators?: string[];
defaultOperator?: string;
defaultValue?: any;
values?: Array<{ name: string; label: string; disabled?: boolean }>;
metricOptions?: Array<{ name: string; label: string }>; // For budgetNumber type
description?: string; // Helpful note for the user
}
export const baseRoutingFields: CELFieldDefinition[] = [
{
name: "model",
label: "Model",
placeholder: "e.g., gpt-4, claude-3-sonnet",
inputType: "text",
valueEditorType: (operator: string) =>
operator === "=" || operator === "!=" ? "select" : operator === "in" || operator === "notIn" ? "select" : "text",
operators: ["=", "!=", "in", "notIn", "contains", "beginsWith", "endsWith", "matches"],
defaultOperator: "=",
},
{
name: "provider",
label: "Provider",
placeholder: "Select provider",
inputType: "select",
valueEditorType: (operator: string) =>
operator === "matches" ? "text" : operator === "in" || operator === "notIn" ? "select" : "select",
operators: ["=", "!=", "in", "notIn", "matches", "null", "notNull"],
defaultOperator: "=",
},
{
name: "request_type",
label: "Request Type",
placeholder: "Select request type",
inputType: "select",
valueEditorType: (operator: string) =>
operator === "matches" ? "text" : operator === "in" || operator === "notIn" ? "select" : "select",
operators: ["=", "!=", "in", "notIn", "matches"],
defaultOperator: "=",
values: [
{ name: "text_completion", label: "Text Completion" },
{ name: "chat_completion", label: "Chat Completion" },
{ name: "responses", label: "Responses" },
{ name: "embedding", label: "Embeddings" },
{ name: "image_generation", label: "Image Generation" },
{ name: "image_edit", label: "Image Edit" },
{ name: "image_variation", label: "Image Variation" },
{ name: "speech", label: "Speech" },
{ name: "transcription", label: "Transcription" },
{ name: "count_tokens", label: "Count Tokens" },
{ name: "rerank", label: "Rerank" },
{ name: "video_generation", label: "Video Generation" },
],
description: "Filter rules by the type of API request (chat, text, embeddings, images, audio, etc.)",
},
{
name: "headers",
label: "Header",
placeholder: "e.g., authorization, x-custom-header (use lowercase)",
inputType: "keyValue",
valueEditorType: "keyValue",
operators: ["=", "!=", "contains", "beginsWith", "endsWith", "matches", "null", "notNull"],
defaultOperator: "=",
},
{
name: "tokens_used",
label: "Tokens Used (%)",
placeholder: "e.g., 80",
inputType: "text",
valueEditorType: "number",
operators: ["=", "!=", ">", "<", ">=", "<="],
defaultOperator: ">=",
description: "Check token usage as percentage. Checked against max of model and provider configs.",
},
{
name: "request",
label: "Request (%)",
placeholder: "e.g., 80",
inputType: "text",
valueEditorType: "number",
operators: ["=", "!=", ">", "<", ">=", "<="],
defaultOperator: ">=",
description: "Check request usage as percentage. Checked against max of model and provider configs.",
},
{
name: "budget_used",
label: "Budget Used (%)",
placeholder: "e.g., 50",
inputType: "text",
valueEditorType: "number",
operators: ["=", "!=", ">", "<", ">=", "<="],
defaultOperator: ">=",
description: "Check budget usage as percentage. Checked against max of model and provider configs.",
},
{
name: "params",
label: "Query Parameter",
placeholder: "e.g., api_key, user_id",
inputType: "keyValue",
valueEditorType: "keyValue",
operators: ["=", "!=", "contains", "beginsWith", "endsWith", "matches", "null", "notNull"],
defaultOperator: "=",
},
];
/**
* Get routing fields with dynamic providers and models
* Provider field values are populated dynamically from available providers
* Metric options for rate limits and budget are populated from available providers and models
*/
export function getRoutingFields(providers: string[] = [], models: string[] = []): CELFieldDefinition[] {
// Create provider field values
const providerValues =
providers.length > 0
? providers.map((provider) => ({
name: provider,
label: getProviderLabel(provider),
}))
: [{ name: "_no_providers", label: "No providers configured", disabled: true }];
// Create model field values
const modelValues =
models.length > 0
? models.map((model) => ({
name: model,
label: model,
}))
: [];
// Create metric options for scope input: providers + models
const scopeOptions = [
{ name: "", label: "(provider-level)" }, // Empty scope for provider-level
...providers.map((provider) => ({
name: provider,
label: `${provider} (provider)`,
})),
...models.map((model) => ({
name: model,
label: `${model} (model)`,
})),
];
// Update provider field with dynamic values and rate limit/budget fields with scope options
const fieldsWithDynamicValues = baseRoutingFields.map((field) => {
if (field.name === "provider") {
return {
...field,
values: providerValues,
};
}
if (field.name === "model") {
return {
...field,
values: modelValues,
};
}
if (field.name === "tokens_used" || field.name === "request" || field.name === "budget_used") {
return {
...field,
metricOptions: scopeOptions,
};
}
return field;
});
return fieldsWithDynamicValues;
}
export const PROVIDER_DISPLAY_NAMES: Record<string, string> = {
openai: "OpenAI",
anthropic: "Anthropic",
azure: "Azure OpenAI",
gemini: "Google Gemini",
vertex: "Vertex AI",
cohere: "Cohere",
};

View File

@@ -0,0 +1,50 @@
/**
* CEL Operators Configuration for Routing Rules
* Maps UI operators to CEL syntax
*/
export interface CELOperatorDefinition {
name: string;
label: string;
celSyntax: string;
}
export const celOperatorsRouting: CELOperatorDefinition[] = [
// Comparison operators
{ name: "=", label: "equals", celSyntax: "==" },
{ name: "!=", label: "does not equal", celSyntax: "!=" },
{ name: ">", label: "greater than", celSyntax: ">" },
{ name: "<", label: "less than", celSyntax: "<" },
{ name: ">=", label: "greater than or equal", celSyntax: ">=" },
{ name: "<=", label: "less than or equal", celSyntax: "<=" },
// List operators
{ name: "in", label: "is in list", celSyntax: "in" },
{ name: "notIn", label: "is not in list", celSyntax: "!in" },
// String operators
{ name: "contains", label: "contains", celSyntax: "contains" },
{ name: "beginsWith", label: "begins with", celSyntax: "startsWith" },
{ name: "endsWith", label: "ends with", celSyntax: "endsWith" },
{ name: "matches", label: "matches (regex)", celSyntax: "matches" },
// Existence operators
{ name: "null", label: "does not exist", celSyntax: "!has" },
{ name: "notNull", label: "exists", celSyntax: "has" },
];
/**
* Get CEL syntax for a given operator name
*/
export function getOperatorCELSyntax(operatorName: string): string {
const operator = celOperatorsRouting.find((op) => op.name === operatorName);
return operator ? operator.celSyntax : operatorName;
}
/**
* Get operator label for display
*/
export function getOperatorLabel(operatorName: string): string {
const operator = celOperatorsRouting.find((op) => op.name === operatorName);
return operator ? operator.label : operatorName;
}