import { useMutation, useSuspenseQuery } from '@tanstack/react-query' import { Link, useNavigate } from '@tanstack/react-router' import { api, json, read } from '../../../shared/api.ts' import { messageOf } from '../../../shared/errors.ts' import { formKey, useAppForm } from '../../../shared/form.tsx' import { ArrowLeftIcon } from '../../../shared/icons.tsx' import { backLink, Callout, ConfirmButton, SaveBar, SettingRow, SettingsGroup, SettingsPage, } from '../../../shared/ui/SettingsPage.tsx' import { capabilities } from '../../models/capabilities.ts' import { RolePicker } from '../components/RolePicker.tsx' import { useModelsChanged } from '../hooks/changes.ts' import { type AdminModel, storedModel } from '../lib/models.ts' import { rolesWithUser } from '../lib/roles.ts' import { adminModelsQuery, adminRolesQuery } from '../queries.ts' interface ModelAdminProps { pluginId: string provider: string modelId: string } /** One of a plugin's admin models on its own page. */ export function ModelAdmin(props: ModelAdminProps) { const { data: models } = useSuspenseQuery(adminModelsQuery) const { data: roles } = useSuspenseQuery(adminRolesQuery) const navigate = useNavigate() const modelsChanged = useModelsChanged() const save = useMutation({ mutationFn: (model: AdminModel) => read(api.admin.models.$put({}, json(model))), onSuccess: modelsChanged, }) const remove = useMutation({ mutationFn: () => read(api.admin.models.$delete({}, json({ provider: props.provider, id: props.modelId }))), // Leave first, so the page doesn't say the model it just removed isn't offered. onSuccess: async () => { await navigate({ to: '/admin/plugins/$id', params: { id: props.pluginId } }) await modelsChanged() }, }) const model = models.find( (candidate) => candidate.provider === props.provider && candidate.id === props.modelId, ) const back = ( Plugin ) if (!model) return (

This model isn't offered.

) return ( {model.provider}/{model.id} } back={back} > {model.warning && (

{model.warning}

)} {messageOf(remove.error)}

) } > remove.mutate()} />
) } interface ModelFormProps { model: AdminModel roleNames: string[] pending: boolean saved: boolean error?: string | null onSave: (model: AdminModel) => void /** Called on any change, since what is shown is no longer what was saved. */ onEdit: () => void } /** One admin model's name, capabilities, and roles. */ function ModelForm(props: ModelFormProps) { const form = useAppForm({ defaultValues: props.model, listeners: { onChange: () => props.onEdit() }, onSubmit: ({ value }) => props.onSave(value), }) return ( {(field) => ( )} {capabilities.map((capability) => ( {(field) => ( )} ))} {(field) => ( )} ) }