Skip to content

Commit

Permalink
feat: improve thread breadcrumbs (#615)
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanhopperlowe authored Nov 18, 2024
1 parent cc9ee4e commit 57964ec
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 57 deletions.
6 changes: 1 addition & 5 deletions ui/admin/app/components/agent/Publish.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,7 @@ type PublishProps = {
onPublish: (alias: string) => void;
};

export function Publish({
className,
alias: _alias,
onPublish,
}: PublishProps) {
export function Publish({ className, alias: _alias, onPublish }: PublishProps) {
const [alias, setAlias] = useState(_alias);

const handlePublish = () => onPublish(alias);
Expand Down
6 changes: 3 additions & 3 deletions ui/admin/app/components/chat/ChatContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ interface ChatContextType {
mode: Mode;
processUserMessage: (text: string, sender: "user" | "agent") => void;
id: string;
threadId: string | undefined;
threadId: Nullish<string>;
invoke: (prompt?: string) => void;
readOnly?: boolean;
isRunning: boolean;
Expand All @@ -42,7 +42,7 @@ export function ChatProvider({
children: ReactNode;
mode?: Mode;
id: string;
threadId?: string;
threadId?: Nullish<string>;
onCreateThreadId?: (threadId: string) => void;
readOnly?: boolean;
}) {
Expand Down Expand Up @@ -116,7 +116,7 @@ export function useChat() {
return context;
}

function useMessageSource(threadId?: string) {
function useMessageSource(threadId?: Nullish<string>) {
const [messages, setMessages] = useState<Message[]>([]);
const [isRunning, setIsRunning] = useState(false);

Expand Down
44 changes: 35 additions & 9 deletions ui/admin/app/components/header/HeaderNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ function RouteBreadcrumbs() {
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
{routeInfo?.path === "/agents/:agent" ? (

{routeInfo?.path === "/agents/:agent" && (
<>
<BreadcrumbItem>
<BreadcrumbLink asChild>
Expand All @@ -76,18 +77,34 @@ function RouteBreadcrumbs() {
</BreadcrumbPage>
</BreadcrumbItem>
</>
) : (
routeInfo?.path === "/agents" && (
<BreadcrumbItem>
<BreadcrumbPage>Agents</BreadcrumbPage>
</BreadcrumbItem>
)
)}
{routeInfo?.path === "/threads" && (

{routeInfo?.path === "/agents" && (
<BreadcrumbItem>
<BreadcrumbPage>Threads</BreadcrumbPage>
<BreadcrumbPage>Agents</BreadcrumbPage>
</BreadcrumbItem>
)}

{routeInfo?.path === "/threads" && (
<>
{routeInfo.query?.from && (
<>
<BreadcrumbItem>
<BreadcrumbLink asChild>
{renderThreadFrom(routeInfo.query.from)}
</BreadcrumbLink>
</BreadcrumbItem>

<BreadcrumbSeparator />
</>
)}

<BreadcrumbItem>
<BreadcrumbPage>Threads</BreadcrumbPage>
</BreadcrumbItem>
</>
)}

{routeInfo?.path === "/thread/:id" && (
<>
<BreadcrumbItem>
Expand Down Expand Up @@ -144,6 +161,15 @@ function RouteBreadcrumbs() {
);
}

const renderThreadFrom = (from: "agents" | "workflows" | "users") => {
if (from === "agents") return <Link to={$path("/agents")}>Agents</Link>;

if (from === "workflows")
return <Link to={$path("/workflows")}>Workflows</Link>;

if (from === "users") return <Link to={$path("/users")}>Users</Link>;
};

const AgentName = ({ agentId }: { agentId: string }) => {
const { data: agent } = useSWR(
AgentService.getAgentById.key(agentId),
Expand Down
13 changes: 7 additions & 6 deletions ui/admin/app/lib/service/routeService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import { ZodNull, ZodSchema, ZodType, z } from "zod";

const QuerySchemas = {
agentSchema: z.object({
threadId: z.string().optional(),
from: z.string().optional(),
threadId: z.string().nullish(),
from: z.string().nullish(),
}),
threadsListSchema: z.object({
agentId: z.string().optional(),
userId: z.string().optional(),
workflowId: z.string().optional(),
agentId: z.string().nullish(),
userId: z.string().nullish(),
workflowId: z.string().nullish(),
from: z.enum(["workflows", "agents", "users"]).nullish().catch(null),
}),
} as const;

Expand Down Expand Up @@ -117,7 +118,7 @@ type PathInfo<T extends keyof RoutesWithParams> = ReturnType<
typeof $params<T, Routes[T]["params"]>
>;

type RouteInfo<T extends keyof Routes = keyof Routes> = {
export type RouteInfo<T extends keyof Routes = keyof Routes> = {
path: T;
query: QueryInfo<T> | null;
pathParams: T extends keyof RoutesWithParams ? PathInfo<T> : unknown;
Expand Down
1 change: 1 addition & 0 deletions ui/admin/app/routes/_auth.agents._index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ export default function Agents() {
<Link
to={$path("/threads", {
agentId: info.row.original.id,
from: "agents",
})}
className="px-0"
>
Expand Down
70 changes: 36 additions & 34 deletions ui/admin/app/routes/_auth.threads.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from "@remix-run/react";
import { ColumnDef, createColumnHelper } from "@tanstack/react-table";
import { PuzzleIcon, Trash, XIcon } from "lucide-react";
import { useCallback, useMemo } from "react";
import { useMemo } from "react";
import { $path } from "remix-routes";
import useSWR, { preload } from "swr";

Expand Down Expand Up @@ -278,43 +278,45 @@ function ThreadFilters({
agentMap: Record<string, Agent>;
workflowMap: Record<string, Workflow>;
}) {
const [searchParams, setSearchParams] = useSearchParams();

const removeParam = useCallback(
(key: string) =>
setSearchParams((prev) => {
const params = new URLSearchParams(prev);
params.delete(key);
return params;
}),
[setSearchParams]
);
const [searchParams] = useSearchParams();
const navigate = useNavigate();

const filters = useMemo(() => {
const threadFilters = {
agentId: (value: string) => agentMap[value]?.name ?? value,
userId: (value: string) => userMap[value]?.email ?? "-",
workflowId: (value: string) => workflowMap[value]?.name ?? value,
const query =
RouteService.getQueryParams("/threads", searchParams.toString()) ??
{};
const { from: _, ...filters } = query;

const updateFilters = (param: keyof typeof filters) => {
// note(ryanhopperlowe) this is a hack because setting a param to null/undefined
// appends "null" to the query string.
const newQuery = structuredClone(query);
delete newQuery[param];
return navigate($path("/threads", newQuery));
};

const labels = {
agentId: "Agent",
userId: "User",
workflowId: "Workflow",
};

const query = RouteService.getQueryParams(
"/threads",
searchParams.toString()
);

return Object.entries(query ?? {}).map(([key, value]) => ({
key,
label: labels[key as keyof SearchParams],
value: threadFilters[key as keyof SearchParams](value),
onRemove: () => removeParam(key),
}));
}, [agentMap, removeParam, searchParams, userMap, workflowMap]);
return [
filters.agentId && {
key: "agentId",
label: "Agent",
value: agentMap[filters.agentId]?.name ?? filters.agentId,
onRemove: () => updateFilters("agentId"),
},
filters.userId && {
key: "userId",
label: "User",
value: userMap[filters.userId]?.email ?? filters.userId,
onRemove: () => updateFilters("userId"),
},
filters.workflowId && {
key: "workflowId",
label: "Workflow",
value:
workflowMap[filters.workflowId]?.name ?? filters.workflowId,
onRemove: () => updateFilters("workflowId"),
},
].filter((x) => !!x);
}, [agentMap, navigate, searchParams, userMap, workflowMap]);

return (
<div className="flex gap-2">
Expand Down
1 change: 1 addition & 0 deletions ui/admin/app/routes/_auth.users.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export default function Users() {
<Link
to={$path("/threads", {
userId: row.original.id,
from: "users",
})}
className="underline"
>
Expand Down
1 change: 1 addition & 0 deletions ui/admin/app/routes/_auth.workflows._index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export default function Workflows() {
<Link
to={$path("/threads", {
workflowId: info.row.original.id,
from: "workflows",
})}
className="px-0"
>
Expand Down

0 comments on commit 57964ec

Please sign in to comment.