diff --git a/skyvern-frontend/src/api/types.ts b/skyvern-frontend/src/api/types.ts index f01acf9b..70df7e84 100644 --- a/skyvern-frontend/src/api/types.ts +++ b/skyvern-frontend/src/api/types.ts @@ -81,3 +81,23 @@ export type TaskApiResponse = { export type User = { name: string; }; + +export type OrganizationApiResponse = { + created_at: string; + modified_at: string; + max_retries_per_step: number | null; + max_steps_per_run: number | null; + organization_id: string; + organization_name: string; + webhook_callback_url: string | null; +}; + +export type ApiKeyApiResponse = { + id: string; + organization_id: string; + token: string; + created_at: string; + modified_at: string; + token_type: string; + valid: boolean; +}; diff --git a/skyvern-frontend/src/hooks/useApiCredential.ts b/skyvern-frontend/src/hooks/useApiCredential.ts new file mode 100644 index 00000000..0d63f0f7 --- /dev/null +++ b/skyvern-frontend/src/hooks/useApiCredential.ts @@ -0,0 +1,39 @@ +import { useQuery } from "@tanstack/react-query"; +import { useCredentialGetter } from "./useCredentialGetter"; +import { getClient } from "@/api/AxiosClient"; +import { envCredential } from "@/util/env"; +import { ApiKeyApiResponse, OrganizationApiResponse } from "@/api/types"; + +function useApiCredential() { + const credentialGetter = useCredentialGetter(); + const credentialsFromEnv = envCredential; + + const { data: organizations } = useQuery>({ + queryKey: ["organizations"], + queryFn: async () => { + const client = await getClient(credentialGetter); + return await client + .get("/organizations/") + .then((response) => response.data.organizations); + }, + enabled: envCredential === null, + }); + + const organization = organizations?.[0]; + const organizationId = organization?.organization_id; + + const { data: apiKeys } = useQuery>({ + queryKey: ["apiKeys", organizationId], + queryFn: async () => { + const client = await getClient(credentialGetter); + return await client + .get(`/organizations/${organizationId}/apikeys`) + .then((response) => response.data.api_keys); + }, + enabled: !!organizationId, // don't run this until organization id exists + }); + + return credentialsFromEnv ?? apiKeys?.[0]?.token ?? null; +} + +export { useApiCredential }; diff --git a/skyvern-frontend/src/routes/tasks/create/CreateNewTaskForm.tsx b/skyvern-frontend/src/routes/tasks/create/CreateNewTaskForm.tsx index 1b083369..a72bd45d 100644 --- a/skyvern-frontend/src/routes/tasks/create/CreateNewTaskForm.tsx +++ b/skyvern-frontend/src/routes/tasks/create/CreateNewTaskForm.tsx @@ -33,8 +33,9 @@ import { import { ToastAction } from "@radix-ui/react-toast"; import { Link } from "react-router-dom"; import fetchToCurl from "fetch-to-curl"; -import { apiBaseUrl, envCredential } from "@/util/env"; +import { apiBaseUrl } from "@/util/env"; import { useCredentialGetter } from "@/hooks/useCredentialGetter"; +import { useApiCredential } from "@/hooks/useApiCredential"; const createNewTaskFormSchema = z.object({ url: z.string().url({ @@ -70,6 +71,7 @@ function CreateNewTaskForm({ initialValues }: Props) { const queryClient = useQueryClient(); const { toast } = useToast(); const credentialGetter = useCredentialGetter(); + const apiCredential = useApiCredential(); const form = useForm({ resolver: zodResolver(createNewTaskFormSchema), @@ -302,7 +304,7 @@ function CreateNewTaskForm({ initialValues }: Props) { body: createTaskRequestObject(form.getValues()), headers: { "Content-Type": "application/json", - "x-api-key": envCredential ?? "", + "x-api-key": apiCredential ?? "", }, }); await navigator.clipboard.writeText(curl);