Add advanced settings in prompt box (#1655)

This commit is contained in:
Shuchang Zheng
2025-01-27 21:47:09 +08:00
committed by GitHub
parent 16ff41f999
commit 7f2413e06d
2 changed files with 134 additions and 63 deletions

View File

@@ -257,3 +257,9 @@ export type ObserverTask = {
output: Record<string, unknown> | null; output: Record<string, unknown> | null;
summary: string | null; summary: string | null;
}; };
export type Createv2TaskRequest = {
user_prompt: string;
webhook_callback_url?: string | null;
proxy_location?: ProxyLocation | null;
};

View File

@@ -1,5 +1,10 @@
import { getClient } from "@/api/AxiosClient"; import { getClient } from "@/api/AxiosClient";
import { ObserverTask, TaskGenerationApiResponse } from "@/api/types"; import {
Createv2TaskRequest,
ObserverTask,
ProxyLocation,
TaskGenerationApiResponse,
} from "@/api/types";
import img from "@/assets/promptBoxBg.png"; import img from "@/assets/promptBoxBg.png";
import { AutoResizingTextarea } from "@/components/AutoResizingTextarea/AutoResizingTextarea"; import { AutoResizingTextarea } from "@/components/AutoResizingTextarea/AutoResizingTextarea";
import { CartIcon } from "@/components/icons/CartIcon"; import { CartIcon } from "@/components/icons/CartIcon";
@@ -37,6 +42,8 @@ import {
generateUniqueEmail, generateUniqueEmail,
} from "../data/sampleTaskData"; } from "../data/sampleTaskData";
import { ExampleCasePill } from "./ExampleCasePill"; import { ExampleCasePill } from "./ExampleCasePill";
import { Input } from "@/components/ui/input";
import { ProxySelector } from "@/components/ProxySelector";
function createTemplateTaskFromTaskGenerationParameters( function createTemplateTaskFromTaskGenerationParameters(
values: TaskGenerationApiResponse, values: TaskGenerationApiResponse,
@@ -137,13 +144,24 @@ function PromptBox() {
const [selectValue, setSelectValue] = useState<"v1" | "v2">("v2"); // Observer is the default const [selectValue, setSelectValue] = useState<"v1" | "v2">("v2"); // Observer is the default
const credentialGetter = useCredentialGetter(); const credentialGetter = useCredentialGetter();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const [webhookCallbackUrl, setWebhookCallbackUrl] = useState<string | null>(
null,
);
const [proxyLocation, setProxyLocation] = useState<ProxyLocation>(
ProxyLocation.Residential,
);
const [showAdvancedSettings, setShowAdvancedSettings] = useState(false);
const startObserverCruiseMutation = useMutation({ const startObserverCruiseMutation = useMutation({
mutationFn: async (prompt: string) => { mutationFn: async (prompt: string) => {
const client = await getClient(credentialGetter, "v2"); const client = await getClient(credentialGetter, "v2");
return client.post<{ user_prompt: string }, { data: ObserverTask }>( return client.post<Createv2TaskRequest, { data: ObserverTask }>(
"/tasks", "/tasks",
{ user_prompt: prompt }, {
user_prompt: prompt,
webhook_callback_url: webhookCallbackUrl,
proxy_location: proxyLocation,
},
); );
}, },
onSuccess: (response) => { onSuccess: (response) => {
@@ -190,10 +208,11 @@ function PromptBox() {
.then((response) => response.data); .then((response) => response.data);
}, },
onError: (error: AxiosError) => { onError: (error: AxiosError) => {
const detail = (error.response?.data as { detail?: string })?.detail;
toast({ toast({
variant: "destructive", variant: "destructive",
title: "Error creating task from prompt", title: "Error creating task from prompt",
description: error.message, description: detail ? detail : error.message,
}); });
}, },
}); });
@@ -236,7 +255,8 @@ function PromptBox() {
<span className="text-2xl"> <span className="text-2xl">
What task would you like to accomplish? What task would you like to accomplish?
</span> </span>
<div className="flex w-full max-w-xl items-center rounded-xl bg-slate-700 py-2 pr-4 lg:w-3/4"> <div className="flex w-full max-w-xl flex-col">
<div className="flex w-full items-center gap-2 rounded-xl bg-slate-700 py-2 pr-4">
<AutoResizingTextarea <AutoResizingTextarea
className="min-h-0 resize-none rounded-xl border-transparent px-4 hover:border-transparent focus-visible:ring-0" className="min-h-0 resize-none rounded-xl border-transparent px-4 hover:border-transparent focus-visible:ring-0"
value={prompt} value={prompt}
@@ -275,14 +295,22 @@ function PromptBox() {
</CustomSelectItem> </CustomSelectItem>
</SelectContent> </SelectContent>
</Select> </Select>
<div className="flex items-center">
<GearIcon
className="size-6 cursor-pointer"
onClick={() => {
setShowAdvancedSettings((value) => !value);
}}
/>
</div>
<div className="flex items-center"> <div className="flex items-center">
{startObserverCruiseMutation.isPending || {startObserverCruiseMutation.isPending ||
getTaskFromPromptMutation.isPending || getTaskFromPromptMutation.isPending ||
saveTaskMutation.isPending ? ( saveTaskMutation.isPending ? (
<ReloadIcon className="h-6 w-6 animate-spin" /> <ReloadIcon className="size-6 animate-spin" />
) : ( ) : (
<PaperPlaneIcon <PaperPlaneIcon
className="h-6 w-6 cursor-pointer" className="size-6 cursor-pointer"
onClick={async () => { onClick={async () => {
if (selectValue === "v2") { if (selectValue === "v2") {
startObserverCruiseMutation.mutate(prompt); startObserverCruiseMutation.mutate(prompt);
@@ -290,7 +318,9 @@ function PromptBox() {
} }
const taskGenerationResponse = const taskGenerationResponse =
await getTaskFromPromptMutation.mutateAsync(prompt); await getTaskFromPromptMutation.mutateAsync(prompt);
await saveTaskMutation.mutateAsync(taskGenerationResponse); await saveTaskMutation.mutateAsync(
taskGenerationResponse,
);
navigate("/tasks/create/from-prompt", { navigate("/tasks/create/from-prompt", {
state: { state: {
data: taskGenerationResponse, data: taskGenerationResponse,
@@ -301,6 +331,41 @@ function PromptBox() {
)} )}
</div> </div>
</div> </div>
{showAdvancedSettings ? (
<div className="rounded-b-lg px-2">
<div className="space-y-4 rounded-b-xl bg-slate-900 p-4">
<header>Advanced Settings</header>
<div className="flex gap-16">
<div className="w-96">
<div className="text-sm">Webhook Callback URL</div>
<div className="text-xs text-slate-400">
The URL of a webhook endpoint to send the extracted
information
</div>
</div>
<Input
value={webhookCallbackUrl ?? ""}
onChange={(event) => {
setWebhookCallbackUrl(event.target.value);
}}
/>
</div>
<div className="flex gap-16">
<div className="w-96">
<div className="text-sm">Proxy Location</div>
<div className="text-xs text-slate-400">
Route Skyvern through one of our available proxies.
</div>
</div>
<ProxySelector
value={proxyLocation}
onChange={setProxyLocation}
/>
</div>
</div>
</div>
) : null}
</div>
</div> </div>
</div> </div>
<div className="flex flex-wrap justify-center gap-4 rounded-sm bg-slate-elevation1 p-4"> <div className="flex flex-wrap justify-center gap-4 rounded-sm bg-slate-elevation1 p-4">