Skip to main content
Glama

@arizeai/phoenix-mcp

Official
by Arize-ai
SavePromptForm.tsx5.95 kB
import { useCallback, useRef, useState } from "react"; import { Controller, useForm } from "react-hook-form"; import { graphql, useLazyLoadQuery } from "react-relay"; import { Button, FieldError, Flex, Form, Label, Text, TextArea, TextField, View, } from "@phoenix/components"; import { SavePromptFormQuery } from "@phoenix/pages/playground/__generated__/SavePromptFormQuery.graphql"; import { PromptComboBox } from "@phoenix/pages/playground/PromptComboBox"; import { identifierPattern } from "@phoenix/utils/identifierUtils"; export type SavePromptSubmitHandler = ( params: SavePromptFormParams, close: () => void ) => void; export type SavePromptFormParams = { promptId?: string; name: string; description?: string; }; export function SavePromptForm({ onCreate, onUpdate, isSubmitting = false, defaultSelectedPromptId, onClose, }: { onCreate: SavePromptSubmitHandler; onUpdate: SavePromptSubmitHandler; isSubmitting?: boolean; defaultSelectedPromptId?: string; onClose: () => void; }) { const flexContainer = useRef<HTMLDivElement>(null); const prompts = useLazyLoadQuery<SavePromptFormQuery>( graphql` query SavePromptFormQuery { prompts(first: 200) { edges { prompt: node { id name } } } } `, {}, { fetchPolicy: "network-only" } ); const [selectedPromptId, setSelectedPromptId] = useState<string | null>( defaultSelectedPromptId ?? null ); const selectedPrompt = prompts?.prompts?.edges?.find( (edge) => edge?.prompt?.id === selectedPromptId ); const [promptInputValue, setPromptInputValue] = useState<string>( selectedPrompt?.prompt?.name ?? "" ); const mode: "create" | "update" = selectedPrompt ? "update" : "create"; const submitButtonText = mode === "create" ? "Create Prompt" : "Update Prompt"; const { control, handleSubmit, formState: { isDirty, isValid }, trigger, } = useForm<SavePromptFormParams>({ values: { promptId: selectedPromptId ?? undefined, name: mode === "update" && selectedPrompt ? selectedPrompt?.prompt?.name : promptInputValue, }, defaultValues: { description: "", }, reValidateMode: "onChange", resetOptions: { keepDefaultValues: true, }, }); const onSubmit = useCallback( (params: SavePromptFormParams) => { if (mode === "create") { onCreate(params, onClose); } else { onUpdate(params, onClose); } }, [onCreate, onUpdate, mode, onClose] ); return ( <Flex direction="column" gap="size-100" ref={flexContainer}> <View paddingX="size-200" paddingTop="size-200"> <Controller name="name" control={control} rules={{ required: { message: "Prompt is required", value: true, }, pattern: identifierPattern, }} render={({ field: { onBlur, onChange }, fieldState }) => ( <PromptComboBox label="Prompt" description="The prompt to update, or prompt name to create" placeholder="Select or enter new prompt name" isRequired onBlur={onBlur} defaultInputValue={promptInputValue} onInputChange={(value) => { setPromptInputValue(value); onChange(value); trigger("name"); }} // this seems... not great. not sure how else to get a stable element reference that doesn't use a ref // https://react-spectrum.adobe.com/react-aria/Popover.html#props // eslint-disable-next-line react-compiler/react-compiler container={flexContainer.current ?? undefined} errorMessage={fieldState.error?.message} allowsCustomValue onChange={(promptId) => { onChange(promptId); setSelectedPromptId(promptId); }} promptId={selectedPromptId} /> )} /> </View> <Form onSubmit={handleSubmit(onSubmit)}> <View paddingX="size-200" paddingBottom="size-200"> <Controller name="description" control={control} render={({ field: { onChange, onBlur, value }, fieldState: { invalid, error }, }) => ( <TextField isInvalid={invalid} onChange={onChange} onBlur={onBlur} value={value} size="S" > <Label> {mode === "create" ? "Prompt Description" : "Change Description"} </Label> <TextArea /> {error ? ( <FieldError>{error.message}</FieldError> ) : ( <Text slot="description"> {mode === "create" ? "A description of your prompt (optional)" : "A description of your changes to the prompt (optional)"} </Text> )} </TextField> )} /> </View> <View paddingEnd="size-200" paddingTop="size-100" paddingBottom="size-100" borderTopColor="light" borderTopWidth="thin" > <Flex direction="row" justifyContent="end"> <Button variant={isDirty ? "primary" : "default"} size="S" isDisabled={isSubmitting || !isValid} type="submit" > {submitButtonText} </Button> </Flex> </View> </Form> </Flex> ); }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Arize-ai/phoenix'

If you have feedback or need assistance with the MCP directory API, please join our Discord server