feat: self healing skyvern api key (#3614)

Co-authored-by: Suchintan <suchintan@users.noreply.github.com>
Co-authored-by: Shuchang Zheng <wintonzheng0325@gmail.com>
This commit is contained in:
greg niemeyer
2025-10-13 07:55:59 -07:00
committed by GitHub
parent a8179ae61c
commit 2faf4e102f
16 changed files with 638 additions and 46 deletions

View File

@@ -5,6 +5,7 @@ import { Outlet } from "react-router-dom";
import { Header } from "./Header";
import { Sidebar } from "./Sidebar";
import { useDebugStore } from "@/store/useDebugStore";
import { SelfHealApiKeyBanner } from "@/components/SelfHealApiKeyBanner";
function RootLayout() {
const collapsed = useSidebarStore((state) => state.collapsed);
@@ -12,15 +13,21 @@ function RootLayout() {
const isEmbedded = embed === "true";
const debugStore = useDebugStore();
const horizontalPadding = cn("lg:pl-64", {
"lg:pl-28": collapsed,
"lg:pl-4": isEmbedded,
});
return (
<>
{!isEmbedded && <Sidebar />}
<div className="h-full w-full">
<div className={horizontalPadding}>
<SelfHealApiKeyBanner />
</div>
<Header />
<main
className={cn("lg:pb-4 lg:pl-64", {
"lg:pl-28": collapsed,
"lg:pl-4": isEmbedded,
className={cn("lg:pb-4", horizontalPadding, {
"lg:pb-0": debugStore.isDebugMode,
})}
>

View File

@@ -14,7 +14,7 @@ import {
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { envCredential } from "@/util/env";
import { getRuntimeApiKey } from "@/util/env";
import { HiddenCopyableInput } from "@/components/ui/hidden-copyable-input";
import { OnePasswordTokenForm } from "@/components/OnePasswordTokenForm";
import { AzureClientSecretCredentialTokenForm } from "@/components/AzureClientSecretCredentialTokenForm";
@@ -22,7 +22,7 @@ import { AzureClientSecretCredentialTokenForm } from "@/components/AzureClientSe
function Settings() {
const { environment, organization, setEnvironment, setOrganization } =
useSettingsStore();
const apiKey = envCredential;
const apiKey = getRuntimeApiKey();
return (
<div className="flex flex-col gap-8">

View File

@@ -5,7 +5,7 @@ import { toast } from "@/components/ui/use-toast";
import { ZoomableImage } from "@/components/ZoomableImage";
import { useCostCalculator } from "@/hooks/useCostCalculator";
import { useCredentialGetter } from "@/hooks/useCredentialGetter";
import { envCredential } from "@/util/env";
import { getRuntimeApiKey } from "@/util/env";
import {
keepPreviousData,
useQuery,
@@ -79,7 +79,8 @@ function TaskActions() {
const token = await credentialGetter();
credential = `?token=Bearer ${token}`;
} else {
credential = `?apikey=${envCredential}`;
const apiKey = getRuntimeApiKey();
credential = apiKey ? `?apikey=${apiKey}` : "";
}
if (socket) {
socket.close();

View File

@@ -5,7 +5,7 @@ import { useEffect, useState } from "react";
import { statusIsNotFinalized } from "@/routes/tasks/types";
import { useCredentialGetter } from "@/hooks/useCredentialGetter";
import { useParams } from "react-router-dom";
import { envCredential } from "@/util/env";
import { getRuntimeApiKey } from "@/util/env";
import { toast } from "@/components/ui/use-toast";
import { useQueryClient } from "@tanstack/react-query";
@@ -45,7 +45,8 @@ function WorkflowRunStream(props?: Props) {
const token = await credentialGetter();
credential = `?token=Bearer ${token}`;
} else {
credential = `?apikey=${envCredential}`;
const apiKey = getRuntimeApiKey();
credential = apiKey ? `?apikey=${apiKey}` : "";
}
if (socket) {
socket.close();