Skip to content

Commit

Permalink
feat: overhaul agent edit UX
Browse files Browse the repository at this point in the history
This is a pretty substantial overhaul of the agent
edit UX. The main changes are:
- A new "Advanced" tab that allows you to edit the
  prompt
- The name and description now look like contentEditable
  fields (they're not, but they act like them)
- The edit agent page has moved the "go back" button
  to the header
- New "Knowledge" suggestion for preview chats
- Updated "restart chat" button to be "new thread"
  along with a companion button to select past threads
- Accordion options now have color, descriptions, and
  larger text.
- New Agents now have a name of "New Agent" instead of
  the fun random names they used to have.

Signed-off-by: tylerslaton <[email protected]>
  • Loading branch information
tylerslaton committed Oct 22, 2024
1 parent 5e4d6d5 commit 6fef2d2
Show file tree
Hide file tree
Showing 13 changed files with 426 additions and 119 deletions.
109 changes: 89 additions & 20 deletions ui/admin/app/components/Typography.tsx
Original file line number Diff line number Diff line change
@@ -1,114 +1,183 @@
import { ReactNode } from "react";
import React, { ReactNode } from "react";

import { cn } from "~/lib/utils";

interface TypographyProps {
type TypographyElement = keyof JSX.IntrinsicElements;

type TypographyProps<T extends TypographyElement> = {
children: ReactNode;
className?: string;
}
} & React.JSX.IntrinsicElements[T];

export function TypographyH1({ children, className }: TypographyProps) {
export function TypographyH1({
children,
className,
...props
}: TypographyProps<"h1">) {
return (
<h1
className={cn(
`scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl`,
className
)}
{...props}
>
{children}
</h1>
);
}

export function TypographyH2({ children, className }: TypographyProps) {
export function TypographyH2({
children,
className,
...props
}: TypographyProps<"h2">) {
return (
<h2
className={cn(
`scroll-m-20 pb-2 text-3xl font-semibold tracking-tight first:mt-0`,
className
)}
{...props}
>
{children}
</h2>
);
}

export function TypographyH3({ children, className }: TypographyProps) {
export function TypographyH3({
children,
className,
...props
}: TypographyProps<"h3">) {
return (
<h3
className={cn(
`scroll-m-20 text-2xl font-semibold tracking-tight`,
className
)}
{...props}
>
{children}
</h3>
);
}

export function TypographyH4({ children, className }: TypographyProps) {
export function TypographyH4({
children,
className,
...props
}: TypographyProps<"h4">) {
return (
<h4
className={cn(
`scroll-m-20 text-xl font-semibold tracking-tight`,
className
)}
{...props}
>
{children}
</h4>
);
}

export function TypographyP({ children, className }: TypographyProps) {
return <p className={cn(`leading-7`, className)}>{children}</p>;
export function TypographyP({
children,
className,
...props
}: TypographyProps<"p">) {
return (
<p className={cn(`leading-7`, className)} {...props}>
{children}
</p>
);
}

export function TypographyBlockquote({ children, className }: TypographyProps) {
export function TypographyBlockquote({
children,
className,
...props
}: TypographyProps<"blockquote">) {
return (
<blockquote className={cn(`mt-6 border-l-2 pl-6 italic`, className)}>
<blockquote
className={cn(`mt-6 border-l-2 pl-6 italic`, className)}
{...props}
>
{children}
</blockquote>
);
}

export function TypographyInlineCode({ children, className }: TypographyProps) {
export function TypographyInlineCode({
children,
className,
...props
}: TypographyProps<"code">) {
return (
<code
className={cn(
`relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold`,
className
)}
{...props}
>
{children}
</code>
);
}

export function TypographyLead({ children, className }: TypographyProps) {
export function TypographyLead({
children,
className,
...props
}: TypographyProps<"p">) {
return (
<p className={cn(`text-xl text-muted-foreground`, className)}>
<p
className={cn(`text-xl text-muted-foreground`, className)}
{...props}
>
{children}
</p>
);
}

export function TypographyLarge({ children, className }: TypographyProps) {
export function TypographyLarge({
children,
className,
...props
}: TypographyProps<"div">) {
return (
<div className={cn(`text-lg font-semibold`, className)}>{children}</div>
<div className={cn(`text-lg font-semibold`, className)} {...props}>
{children}
</div>
);
}

export function TypographySmall({ children, className }: TypographyProps) {
export function TypographySmall({
children,
className,
...props
}: TypographyProps<"small">) {
return (
<small className={cn(`text-sm font-medium leading-none`, className)}>
<small
className={cn(`text-sm font-medium leading-none`, className)}
{...props}
>
{children}
</small>
);
}

export function TypographyMuted({ children, className }: TypographyProps) {
export function TypographyMuted({
children,
className,
...props
}: TypographyProps<"p">) {
return (
<p className={cn(`text-sm text-muted-foreground`, className)}>
<p
className={cn(`text-sm text-muted-foreground`, className)}
{...props}
>
{children}
</p>
);
Expand Down
65 changes: 65 additions & 0 deletions ui/admin/app/components/agent/AdvancedForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { z } from "zod";

import { Agent } from "~/lib/model/agents";

import { ControlledTextarea } from "~/components/form/controlledInputs";
import { Form } from "~/components/ui/form";

const formSchema = z.object({
prompt: z.string().optional(),
});

export type AdvancedFormValues = z.infer<typeof formSchema>;

type AdvancedFormProps = {
agent: Agent;
onSubmit?: (values: AdvancedFormValues) => void;
onChange?: (values: AdvancedFormValues) => void;
};

export function AdvancedForm({ agent, onSubmit, onChange }: AdvancedFormProps) {
const form = useForm<AdvancedFormValues>({
resolver: zodResolver(formSchema),
mode: "onChange",
defaultValues: {
prompt: agent.prompt || "",
},
});

useEffect(() => {
if (agent) form.reset({ prompt: agent.prompt || "" });
}, [agent, form]);

useEffect(() => {
return form.watch((values) => {
if (!onChange) return;

const { data, success } = formSchema.safeParse(values);

if (!success) return;

onChange(data);
}).unsubscribe;
}, [onChange, form]);

const handleSubmit = form.handleSubmit((values: AdvancedFormValues) =>
onSubmit?.({ ...values })
);

return (
<Form {...form}>
<form onSubmit={handleSubmit} className="space-y-8">
<ControlledTextarea
control={form.control}
name="prompt"
label="Additional Instructions"
description="Give the agent additional instructions on how it should behave."
placeholder="Talk like a pirate."
/>
</form>
</Form>
);
}
Loading

0 comments on commit 6fef2d2

Please sign in to comment.