import { ChevronDown, SlidersHorizontal } from 'lucide-react'; import { useEffect, useState } from 'react'; import type { JSONSchema, JSONSchemaProperty, SessionKnowledgeConfig } from '@/api'; import { Button } from '@/components/ui/button'; import { DropdownMenu, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, } from '@/components/ui/popover'; import { Switch } from '@/components/ui/switch'; import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'; import { useTranslation } from '@/i18n/useI18n'; interface Props { /** * The current session-knowledge config. The popover edits its * `parameters` dict; `knowledge_base_ids` is preserved verbatim. * `null` means no KBs are attached — the trigger is then disabled * because there is nothing for the parameters to act on. */ value: SessionKnowledgeConfig | null; /** JSON Schema describing the middleware's tunable parameters. */ schema: JSONSchema | null; /** Persist a new config back to the session. */ onChange: (next: SessionKnowledgeConfig | null) => void; /** Force-disable the trigger regardless of `value` (e.g. no session). */ disabled?: boolean; } type ParamValue = string | number | boolean | null | undefined; /** Look through `anyOf` to find the property's effective scalar type and * any enum constraint. Pydantic renders `Literal[...]` directly and * `Literal[...] | None` inside the non-null `anyOf` branch. */ function resolve(prop: JSONSchemaProperty): { type: string; enumValues: unknown[] | null; } { if (prop.type && prop.type !== 'null') { return { type: prop.type, enumValues: prop.enum ?? null }; } for (const variant of prop.anyOf ?? []) { const v = variant as JSONSchemaProperty; if (v.type && v.type !== 'null') { return { type: v.type, enumValues: v.enum ?? prop.enum ?? null }; } } return { type: 'string', enumValues: prop.enum ?? null }; } /** * Trigger + popover that edits the `KnowledgeBaseMiddleware` parameters * for the active session. * * Schema-driven (entries come from * `KnowledgeBaseMiddleware.Parameters.model_json_schema()`) but with a * hand-rolled label/control grid so labels stay flush-left and inputs * align in a single right-hand column — same pattern as * {@link ModelParametersPopover}. Enums render as * {@link LlmSelect}-style `DropdownMenu` triggers instead of the native * ` { const raw = e.target.value; if (raw === '') { handleParamChange(key, undefined); return; } const parsed = type === 'integer' ? parseInt(raw, 10) : parseFloat(raw); handleParamChange( key, Number.isNaN(parsed) ? raw : parsed, ); }} /> ); } else { control = ( handleParamChange(key, e.target.value)} /> ); } return (
{control}
{prop.description && ( {prop.description} )}
); })} ) : null} ); }