Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add req sonners #192

Merged
merged 3 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions ui/admin/app/components/ui/sonner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { useTheme } from "next-themes";
import { Toaster as Sonner } from "sonner";

type ToasterProps = React.ComponentProps<typeof Sonner>;

const Toaster = ({ ...props }: ToasterProps) => {
const { theme = "system" } = useTheme();

return (
<Sonner
theme={theme as ToasterProps["theme"]}
className="toaster group"
toastOptions={{
classNames: {
toast: "group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
description: "group-[.toast]:text-muted-foreground",
actionButton:
"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
cancelButton:
"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
},
}}
{...props}
/>
);
};

export { Toaster };
5 changes: 5 additions & 0 deletions ui/admin/app/lib/service/api/agentService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { request } from "~/lib/service/api/primitives";
async function getAgents() {
const res = await request<{ items: Agent[] }>({
url: ApiRoutes.agents.base().url,
errorMessage: "Failed to fetch agents",
});

return res.data.items ?? ([] as Agent[]);
Expand All @@ -14,6 +15,7 @@ getAgents.key = () => ({ url: ApiRoutes.agents.base().path }) as const;
const getAgentById = async (agentId: string) => {
const res = await request<Agent>({
url: ApiRoutes.agents.getById(agentId).url,
errorMessage: "Failed to fetch agent",
});

if (!res.data) return null;
Expand All @@ -31,6 +33,7 @@ async function createAgent({ agent }: { agent: CreateAgent }) {
url: ApiRoutes.agents.base().url,
method: "POST",
data: agent,
errorMessage: "Failed to create agent",
});

return res.data;
Expand All @@ -41,6 +44,7 @@ async function updateAgent({ id, agent }: { id: string; agent: UpdateAgent }) {
url: ApiRoutes.agents.getById(id).url,
method: "PUT",
data: agent,
errorMessage: "Failed to update agent",
});

return res.data;
Expand All @@ -50,6 +54,7 @@ async function deleteAgent(id: string) {
await request({
url: ApiRoutes.agents.getById(id).url,
method: "DELETE",
errorMessage: "Failed to delete agent",
});
}

Expand Down
1 change: 1 addition & 0 deletions ui/admin/app/lib/service/api/invokeService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ async function invokeWithStream({
headers: { Accept: "text/event-stream" },
responseType: "stream",
data: prompt,
errorMessage: "Failed to invoke agent",
});

const reader = response.data
Expand Down
8 changes: 8 additions & 0 deletions ui/admin/app/lib/service/api/knowledgeService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { request } from "~/lib/service/api/primitives";
async function getKnowledgeForAgent(agentId: string, includeDeleted = false) {
const res = await request<{ items: KnowledgeFile[] }>({
url: ApiRoutes.agents.getKnowledge(agentId).url,
errorMessage: "Failed to fetch knowledge for agent",
});

if (includeDeleted) return res.data.items;
Expand All @@ -28,20 +29,23 @@ async function addKnowledgeToAgent(agentId: string, file: File) {
method: "POST",
data: await file.arrayBuffer(),
headers: { "Content-Type": "application/x-www-form-urlencoded" },
errorMessage: "Failed to add knowledge to agent",
});
}

async function deleteKnowledgeFromAgent(agentId: string, fileName: string) {
await request({
url: ApiRoutes.agents.deleteKnowledge(agentId, fileName).url,
method: "DELETE",
errorMessage: "Failed to delete knowledge from agent",
});
}

async function triggerKnowledgeIngestion(agentId: string) {
await request({
url: ApiRoutes.agents.triggerKnowledgeIngestion(agentId).url,
method: "POST",
errorMessage: "Failed to trigger knowledge ingestion",
});
}

Expand All @@ -53,6 +57,7 @@ async function createRemoteKnowledgeSource(
url: ApiRoutes.agents.createRemoteKnowledgeSource(agentId).url,
method: "POST",
data: JSON.stringify(input),
errorMessage: "Failed to create remote knowledge source",
});
return res.data;
}
Expand All @@ -69,6 +74,7 @@ async function updateRemoteKnowledgeSource(
).url,
method: "PUT",
data: JSON.stringify(input),
errorMessage: "Failed to update remote knowledge source",
});
}

Expand All @@ -82,6 +88,7 @@ async function resyncRemoteKnowledgeSource(
remoteKnowledgeSourceId
).url,
method: "PATCH",
errorMessage: "Failed to resync remote knowledge source",
});
}

Expand All @@ -90,6 +97,7 @@ async function getRemoteKnowledgeSource(agentId: string) {
items: RemoteKnowledgeSource[];
}>({
url: ApiRoutes.agents.getRemoteKnowledgeSource(agentId).url,
errorMessage: "Failed to fetch remote knowledge source",
});
return res.data.items;
}
Expand Down
42 changes: 35 additions & 7 deletions ui/admin/app/lib/service/api/primitives.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// TODO: Add default configurations with auth tokens, etc. When ready
import axios from "axios";
import axios, { AxiosRequestConfig, AxiosResponse, isAxiosError } from "axios";
import { toast } from "sonner";

export const ResponseHeaders = {
RunId: "x-otto-run-id",
Expand All @@ -8,9 +9,36 @@ export const ResponseHeaders = {

const internalFetch = axios.request;

export const request: typeof internalFetch = (config) => {
return internalFetch({
adapter: "fetch",
...config,
});
};
interface ExtendedAxiosRequestConfig<D = unknown>
extends AxiosRequestConfig<D> {
errorMessage?: string;
}

export async function request<T, R = AxiosResponse<T>, D = unknown>({
errorMessage = "Request failed",
...config
}: ExtendedAxiosRequestConfig<D>): Promise<R> {
try {
return await internalFetch<T, R, D>({
adapter: "fetch",
...config,
});
} catch (error) {
handleRequestError(error, errorMessage);
throw error;
}
}

function handleRequestError(error: unknown, errorMessage: string): void {
if (isAxiosError(error) && error.response) {
const { status, config } = error.response;
const method = config.method?.toUpperCase() || "UNKNOWN";
toast.error(`${status} ${method}`, {
description: errorMessage,
});
} else {
toast.error("Request Error", {
description: errorMessage,
});
}
}
3 changes: 3 additions & 0 deletions ui/admin/app/lib/service/api/runsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { request } from "~/lib/service/api/primitives";
const getRuns = async () => {
const res = await request<{ items: Run[] }>({
url: ApiRoutes.runs.base().url,
errorMessage: "Failed to fetch runs",
});

return res.data.items ?? ([] as Run[]);
Expand All @@ -14,6 +15,7 @@ getRuns.key = () => ({ url: ApiRoutes.runs.base().path });
const getRunDebugById = async (runId: string) => {
const res = await request<RunDebug>({
url: ApiRoutes.runs.getDebugById(runId).url,
errorMessage: "Failed to fetch run debug",
});

return res.data;
Expand All @@ -27,6 +29,7 @@ getRunDebugById.key = (runId?: Nullish<string>) => {
const getRunsByThread = async (threadId: string) => {
const res = await request<{ items: Run[] }>({
url: ApiRoutes.runs.getByThread(threadId).url,
errorMessage: "Failed to fetch runs by thread",
});

return res.data.items;
Expand Down
7 changes: 7 additions & 0 deletions ui/admin/app/lib/service/api/threadsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { request } from "~/lib/service/api/primitives";
const getThreads = async () => {
const res = await request<{ items: Thread[] }>({
url: ApiRoutes.threads.base().url,
errorMessage: "Failed to fetch threads",
});

return res.data.items ?? ([] as Thread[]);
Expand All @@ -17,6 +18,7 @@ getThreads.key = () => ({ url: ApiRoutes.threads.base().path }) as const;
const getThreadById = async (threadId: string) => {
const res = await request<Thread>({
url: ApiRoutes.threads.getById(threadId).url,
errorMessage: "Failed to fetch thread",
});

return res.data;
Expand All @@ -30,6 +32,7 @@ getThreadById.key = (threadId?: Nullish<string>) => {
const getThreadsByAgent = async (agentId: string) => {
const res = await request<{ items: Thread[] }>({
url: ApiRoutes.threads.getByAgent(agentId).url,
errorMessage: "Failed to fetch threads by agent",
});

return res.data.items ?? ([] as Thread[]);
Expand All @@ -44,6 +47,7 @@ const getThreadEvents = async (threadId: string) => {
const res = await request<{ items: ChatEvent[] }>({
url: ApiRoutes.threads.events(threadId).url,
headers: { Accept: "application/json" },
errorMessage: "Failed to fetch thread events",
});

return res.data.items ?? ([] as ChatEvent[]);
Expand All @@ -58,12 +62,14 @@ const deleteThread = async (threadId: string) => {
await request({
url: ApiRoutes.threads.getById(threadId).url,
method: "DELETE",
errorMessage: "Failed to delete thread",
});
};

const getKnowledge = async (threadId: string) => {
const res = await request<{ items: KnowledgeFile[] }>({
url: ApiRoutes.threads.getKnowledge(threadId).url,
errorMessage: "Failed to fetch knowledge for thread",
});

return res.data.items ?? ([] as KnowledgeFile[]);
Expand All @@ -77,6 +83,7 @@ getKnowledge.key = (threadId?: Nullish<string>) => {
const getFiles = async (threadId: string) => {
const res = await request<{ items: WorkspaceFile[] }>({
url: ApiRoutes.threads.getFiles(threadId).url,
errorMessage: "Failed to fetch files",
});

return res.data.items ?? ([] as WorkspaceFile[]);
Expand Down
6 changes: 6 additions & 0 deletions ui/admin/app/lib/service/api/toolreferenceService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { request } from "~/lib/service/api/primitives";
async function getToolReferences(type?: ToolReferenceType) {
const res = await request<{ items: ToolReference[] }>({
url: ApiRoutes.toolReferences.base({ type }).url,
errorMessage: "Failed to fetch tool references",
});

return res.data.items ?? ([] as ToolReference[]);
Expand All @@ -27,6 +28,7 @@ export type ToolCategoryMap = Record<string, ToolCategory>;
async function getToolReferencesCategoryMap(type?: ToolReferenceType) {
const res = await request<{ items: ToolReference[] }>({
url: ApiRoutes.toolReferences.base({ type }).url,
errorMessage: "Failed to fetch tool references category map",
});

const toolReferences = res.data.items;
Expand Down Expand Up @@ -58,6 +60,7 @@ getToolReferencesCategoryMap.key = (type?: ToolReferenceType) =>
const getToolReferenceById = async (toolReferenceId: string) => {
const res = await request<ToolReference>({
url: ApiRoutes.toolReferences.getById(toolReferenceId).url,
errorMessage: "Failed to fetch tool reference",
});

return res.data;
Expand All @@ -80,6 +83,7 @@ async function createToolReference({
url: ApiRoutes.toolReferences.base().url,
method: "POST",
data: toolReference,
errorMessage: "Failed to create tool reference",
});

return res.data;
Expand All @@ -96,6 +100,7 @@ async function updateToolReference({
url: ApiRoutes.toolReferences.getById(id).url,
method: "PUT",
data: toolReference,
errorMessage: "Failed to update tool reference",
});

return res.data;
Expand All @@ -105,6 +110,7 @@ async function deleteToolReference(id: string) {
await request({
url: ApiRoutes.toolReferences.getById(id).url,
method: "DELETE",
errorMessage: "Failed to delete tool reference",
});
}

Expand Down
5 changes: 5 additions & 0 deletions ui/admin/app/lib/service/api/workflowService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { request } from "~/lib/service/api/primitives";
async function getWorkflows() {
const res = await request<{ items: Workflow[] }>({
url: ApiRoutes.workflows.base().url,
errorMessage: "Failed to fetch workflows",
});

return res.data.items ?? ([] as Workflow[]);
Expand All @@ -18,6 +19,7 @@ getWorkflows.key = () => ({ url: ApiRoutes.workflows.base().path }) as const;
const getWorkflowById = async (workflowId: string) => {
const res = await request<Workflow>({
url: ApiRoutes.workflows.getById(workflowId).url,
errorMessage: "Failed to fetch workflow",
});

return res.data;
Expand All @@ -33,6 +35,7 @@ async function createWorkflow({ workflow }: { workflow: CreateWorkflow }) {
url: ApiRoutes.workflows.base().url,
method: "POST",
data: workflow,
errorMessage: "Failed to create workflow",
});

return res.data;
Expand All @@ -49,6 +52,7 @@ async function updateWorkflow({
url: ApiRoutes.workflows.getById(id).url,
method: "PUT",
data: workflow,
errorMessage: "Failed to update workflow",
});

return res.data;
Expand All @@ -58,6 +62,7 @@ async function deleteWorkflow(id: string) {
await request({
url: ApiRoutes.workflows.getById(id).url,
method: "DELETE",
errorMessage: "Failed to delete workflow",
});
}

Expand Down
2 changes: 2 additions & 0 deletions ui/admin/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {

import { LayoutProvider } from "~/components/layout/LayoutProvider";
import { ThemeProvider } from "~/components/theme";
import { Toaster } from "~/components/ui/sonner";

import "./tailwind.css";

Expand Down Expand Up @@ -39,6 +40,7 @@ export function Layout({ children }: { children: React.ReactNode }) {
</head>
<body>
{children}
<Toaster closeButton />
<ScrollRestoration />
<Scripts />
</body>
Expand Down
Loading