Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 43 additions & 27 deletions app/(main)/guardrails/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
SavedValidatorConfig,
OrgContext,
} from "@/app/lib/types/guardrails";
import { buildValidatorUpdatePayload } from "@/app/lib/utils/guardrails";
import ValidatorConfigPanel from "@/app/components/guardrails/ValidatorConfigPanel";
import SavedConfigsList from "@/app/components/guardrails/SavedConfigsList";

Expand Down Expand Up @@ -61,9 +62,9 @@ export default function GuardrailsPage() {
setValidatorsLoading(true);
guardrailsFetch<{ validators?: Validator[] }>("/api/guardrails", apiKey)
.then((data) => {
const list: Validator[] = Array.isArray(data?.validators)
? data.validators
: [];
const list: Validator[] = (
Array.isArray(data?.validators) ? data.validators : []
).filter((v) => v.type !== "llm_critic");
setValidators(list);
})
.catch(() => toast.error("Failed to load validators"))
Expand All @@ -74,28 +75,34 @@ export default function GuardrailsPage() {
? `?organization_id=${parseInt(String(orgContext.organization_id), 10)}&project_id=${parseInt(String(orgContext.project_id), 10)}`
: null;

const fetchSavedConfigs = useCallback(() => {
if (!configsQueryString) return;
const fetchSavedConfigs = useCallback(async (): Promise<
SavedValidatorConfig[]
> => {
if (!configsQueryString) return [];
setSavedConfigsLoading(true);
guardrailsFetch<{
data?: { configs?: SavedValidatorConfig[] } | SavedValidatorConfig[];
configs?: SavedValidatorConfig[];
}>(`/api/guardrails/validators/configs${configsQueryString}`, apiKey)
.then((data) => {
const nested = data?.data;
const list: SavedValidatorConfig[] = Array.isArray(
(nested as { configs?: SavedValidatorConfig[] })?.configs,
)
? (nested as { configs: SavedValidatorConfig[] }).configs
: Array.isArray(nested)
? (nested as SavedValidatorConfig[])
: Array.isArray(data?.configs)
? data.configs!
: [];
setSavedConfigs(list);
})
.catch(() => toast.error("Failed to load saved configs"))
.finally(() => setSavedConfigsLoading(false));
try {
const data = await guardrailsFetch<{
data?: { configs?: SavedValidatorConfig[] } | SavedValidatorConfig[];
configs?: SavedValidatorConfig[];
}>(`/api/guardrails/validators/configs${configsQueryString}`, apiKey);
const nested = data?.data;
const list: SavedValidatorConfig[] = Array.isArray(
(nested as { configs?: SavedValidatorConfig[] })?.configs,
)
? (nested as { configs: SavedValidatorConfig[] }).configs
: Array.isArray(nested)
? (nested as SavedValidatorConfig[])
: Array.isArray(data?.configs)
? data.configs!
: [];
setSavedConfigs(list);
return list;
} catch {
toast.error("Failed to load saved configs");
return [];
} finally {
setSavedConfigsLoading(false);
}
}, [configsQueryString, apiKey]);

useEffect(() => {
Expand Down Expand Up @@ -150,7 +157,9 @@ export default function GuardrailsPage() {
? `${base}/${selectedSavedConfig!.id}${configsQueryString}`
: `${base}${configsQueryString}`;

const body = configValues;
const body = isUpdate
? buildValidatorUpdatePayload(configValues)
: configValues;

await guardrailsFetch(url, apiKey, {
method: isUpdate ? "PATCH" : "POST",
Expand All @@ -159,8 +168,15 @@ export default function GuardrailsPage() {
toast.success(
isUpdate ? `Config "${name}" updated` : `Config "${name}" saved`,
);
fetchSavedConfigs();
setSelectedSavedConfig(null);
const savedConfigId = selectedSavedConfig?.id;
const freshList = await fetchSavedConfigs();
if (isUpdate && savedConfigId) {
setSelectedSavedConfig(
freshList.find((c) => c.id === savedConfigId) ?? null,
);
} else {
setSelectedSavedConfig(null);
}
} catch (e) {
toast.error(e instanceof Error ? e.message : "Failed to save config");
} finally {
Expand Down
8 changes: 8 additions & 0 deletions app/lib/types/guardrails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,11 @@ export interface OrgContext {
organization_id: number;
project_id: number;
}

export interface ValidatorUpdatePayload {
name?: string;
type?: string;
stage?: string;
on_fail_action?: string; //todo: to consider in future if this variable should be renamed as "on" prefix makes it seems like it is a function
is_enabled?: boolean;
}
14 changes: 14 additions & 0 deletions app/lib/utils/guardrails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { NextRequest } from "next/server";
import type {
ValidatorConfigSchema,
ValidatorMeta,
ValidatorUpdatePayload,
} from "@/app/lib/types/guardrails";
import { VALIDATOR_META } from "@/app/lib/data/guardrails/validators";

Expand Down Expand Up @@ -57,3 +58,16 @@ export function buildDefaultValues(
}
return values;
}

export function buildValidatorUpdatePayload(
configValues: Record<string, unknown>,
): ValidatorUpdatePayload {
const { name, type, stage, on_fail_action, is_enabled } = configValues;
return {
name: name as string,
type: type as string,
stage: stage as string,
on_fail_action: on_fail_action as string,
is_enabled: is_enabled as boolean,
};
}
Loading