Adjust task placeholders (#933)
This commit is contained in:
@@ -174,7 +174,7 @@ export const MultiSelect = React.forwardRef<
|
||||
{...props}
|
||||
onClick={handleTogglePopover}
|
||||
className={cn(
|
||||
"flex h-auto min-h-10 w-full items-center justify-between rounded-md border bg-inherit p-1 hover:bg-inherit",
|
||||
"flex h-auto min-h-8 w-full items-center justify-between rounded-md border bg-inherit p-1 hover:bg-inherit",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
@@ -238,7 +238,7 @@ export const MultiSelect = React.forwardRef<
|
||||
</div>
|
||||
) : (
|
||||
<div className="mx-auto flex w-full items-center justify-between">
|
||||
<span className="mx-3 text-sm font-normal text-muted-foreground">
|
||||
<span className="mx-2 text-xs font-normal text-muted-foreground">
|
||||
{placeholder}
|
||||
</span>
|
||||
<ChevronDownIcon className="mx-2 h-4 cursor-pointer text-muted-foreground" />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getClient } from "@/api/AxiosClient";
|
||||
import { CreateTaskRequest } from "@/api/types";
|
||||
import { CreateTaskRequest, OrganizationApiResponse } from "@/api/types";
|
||||
import { AutoResizingTextarea } from "@/components/AutoResizingTextarea/AutoResizingTextarea";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
@@ -21,7 +21,7 @@ import { apiBaseUrl } from "@/util/env";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { ReloadIcon } from "@radix-ui/react-icons";
|
||||
import { ToastAction } from "@radix-ui/react-toast";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { AxiosError } from "axios";
|
||||
import fetchToCurl from "fetch-to-curl";
|
||||
import { useState } from "react";
|
||||
@@ -91,12 +91,24 @@ function CreateNewTaskForm({ initialValues }: Props) {
|
||||
]);
|
||||
const [showAdvancedBaseContent, setShowAdvancedBaseContent] = useState(false);
|
||||
|
||||
const { data: organizations } = useQuery<Array<OrganizationApiResponse>>({
|
||||
queryKey: ["organizations"],
|
||||
queryFn: async () => {
|
||||
const client = await getClient(credentialGetter);
|
||||
return await client
|
||||
.get("/organizations")
|
||||
.then((response) => response.data.organizations);
|
||||
},
|
||||
});
|
||||
|
||||
const organization = organizations?.[0];
|
||||
|
||||
const form = useForm<CreateNewTaskFormValues>({
|
||||
resolver: zodResolver(createNewTaskFormSchema),
|
||||
defaultValues: initialValues,
|
||||
values: {
|
||||
...initialValues,
|
||||
maxStepsOverride: MAX_STEPS_DEFAULT,
|
||||
maxStepsOverride: null,
|
||||
},
|
||||
});
|
||||
const { errors } = useFormState({ control: form.control });
|
||||
@@ -106,6 +118,7 @@ function CreateNewTaskForm({ initialValues }: Props) {
|
||||
const taskRequest = createTaskRequestObject(formValues);
|
||||
const client = await getClient(credentialGetter);
|
||||
const includeOverrideHeader =
|
||||
formValues.maxStepsOverride !== null &&
|
||||
formValues.maxStepsOverride !== MAX_STEPS_DEFAULT;
|
||||
return client.post<
|
||||
ReturnType<typeof createTaskRequestObject>,
|
||||
@@ -113,8 +126,7 @@ function CreateNewTaskForm({ initialValues }: Props) {
|
||||
>("/tasks", taskRequest, {
|
||||
...(includeOverrideHeader && {
|
||||
headers: {
|
||||
"x-max-steps-override":
|
||||
formValues.maxStepsOverride ?? MAX_STEPS_DEFAULT,
|
||||
"x-max-steps-override": formValues.maxStepsOverride,
|
||||
},
|
||||
}),
|
||||
});
|
||||
@@ -237,8 +249,8 @@ function CreateNewTaskForm({ initialValues }: Props) {
|
||||
<div className="w-full">
|
||||
<FormControl>
|
||||
<AutoResizingTextarea
|
||||
placeholder="Use terms like complete or terminate to give completion directions"
|
||||
{...field}
|
||||
placeholder="Tell Skyvern what to do."
|
||||
value={field.value === null ? "" : field.value}
|
||||
/>
|
||||
</FormControl>
|
||||
@@ -345,8 +357,8 @@ function CreateNewTaskForm({ initialValues }: Props) {
|
||||
<div className="w-full">
|
||||
<FormControl>
|
||||
<AutoResizingTextarea
|
||||
placeholder="e.g. Extract the product price..."
|
||||
{...field}
|
||||
placeholder="What data do you need to extract?"
|
||||
value={field.value === null ? "" : field.value}
|
||||
/>
|
||||
</FormControl>
|
||||
@@ -428,9 +440,14 @@ function CreateNewTaskForm({ initialValues }: Props) {
|
||||
{...field}
|
||||
type="number"
|
||||
min={1}
|
||||
value={field.value}
|
||||
value={field.value ?? ""}
|
||||
placeholder={`Default: ${organization?.max_steps_per_run ?? MAX_STEPS_DEFAULT}`}
|
||||
onChange={(event) => {
|
||||
field.onChange(parseInt(event.target.value));
|
||||
const value =
|
||||
event.target.value === ""
|
||||
? null
|
||||
: Number(event.target.value);
|
||||
field.onChange(value);
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
@@ -458,8 +475,8 @@ function CreateNewTaskForm({ initialValues }: Props) {
|
||||
<div className="w-full">
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder="https://"
|
||||
{...field}
|
||||
placeholder="https://"
|
||||
value={field.value === null ? "" : field.value}
|
||||
/>
|
||||
</FormControl>
|
||||
@@ -517,8 +534,8 @@ function CreateNewTaskForm({ initialValues }: Props) {
|
||||
<div className="w-full">
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder="https://"
|
||||
{...field}
|
||||
placeholder="Provide your 2FA endpoint"
|
||||
value={field.value === null ? "" : field.value}
|
||||
/>
|
||||
</FormControl>
|
||||
@@ -543,8 +560,8 @@ function CreateNewTaskForm({ initialValues }: Props) {
|
||||
<div className="w-full">
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder="Idenfitifer"
|
||||
{...field}
|
||||
placeholder="Add an ID that links your TOTP to the task"
|
||||
value={field.value === null ? "" : field.value}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
@@ -21,7 +21,7 @@ import { apiBaseUrl } from "@/util/env";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { ReloadIcon } from "@radix-ui/react-icons";
|
||||
import { ToastAction } from "@radix-ui/react-toast";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { AxiosError } from "axios";
|
||||
import fetchToCurl from "fetch-to-curl";
|
||||
import { useState } from "react";
|
||||
@@ -31,6 +31,7 @@ import { stringify as convertToYAML } from "yaml";
|
||||
import { MAX_STEPS_DEFAULT } from "../constants";
|
||||
import { TaskFormSection } from "./TaskFormSection";
|
||||
import { savedTaskFormSchema, SavedTaskFormValues } from "./taskFormTypes";
|
||||
import { OrganizationApiResponse } from "@/api/types";
|
||||
|
||||
type Props = {
|
||||
initialValues: SavedTaskFormValues;
|
||||
@@ -142,12 +143,24 @@ function SavedTaskForm({ initialValues }: Props) {
|
||||
]);
|
||||
const [showAdvancedBaseContent, setShowAdvancedBaseContent] = useState(false);
|
||||
|
||||
const { data: organizations } = useQuery<Array<OrganizationApiResponse>>({
|
||||
queryKey: ["organizations"],
|
||||
queryFn: async () => {
|
||||
const client = await getClient(credentialGetter);
|
||||
return await client
|
||||
.get("/organizations")
|
||||
.then((response) => response.data.organizations);
|
||||
},
|
||||
});
|
||||
|
||||
const organization = organizations?.[0];
|
||||
|
||||
const form = useForm<SavedTaskFormValues>({
|
||||
resolver: zodResolver(savedTaskFormSchema),
|
||||
defaultValues: initialValues,
|
||||
values: {
|
||||
...initialValues,
|
||||
maxStepsOverride: initialValues.maxStepsOverride ?? MAX_STEPS_DEFAULT,
|
||||
maxStepsOverride: initialValues.maxStepsOverride ?? null,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -168,6 +181,7 @@ function SavedTaskForm({ initialValues }: Props) {
|
||||
.then(() => {
|
||||
const taskRequest = createTaskRequestObject(formValues);
|
||||
const includeOverrideHeader =
|
||||
formValues.maxStepsOverride !== null &&
|
||||
formValues.maxStepsOverride !== MAX_STEPS_DEFAULT;
|
||||
return client.post<
|
||||
ReturnType<typeof createTaskRequestObject>,
|
||||
@@ -404,8 +418,8 @@ function SavedTaskForm({ initialValues }: Props) {
|
||||
<div className="w-full">
|
||||
<FormControl>
|
||||
<AutoResizingTextarea
|
||||
placeholder="Use terms like complete or terminate to give completion directions"
|
||||
{...field}
|
||||
placeholder="Tell Skyvern what to do."
|
||||
value={field.value === null ? "" : field.value}
|
||||
/>
|
||||
</FormControl>
|
||||
@@ -512,8 +526,8 @@ function SavedTaskForm({ initialValues }: Props) {
|
||||
<div className="w-full">
|
||||
<FormControl>
|
||||
<AutoResizingTextarea
|
||||
placeholder="e.g. Extract the product price..."
|
||||
{...field}
|
||||
placeholder="What data do you need to extract?"
|
||||
value={field.value === null ? "" : field.value}
|
||||
/>
|
||||
</FormControl>
|
||||
@@ -600,9 +614,14 @@ function SavedTaskForm({ initialValues }: Props) {
|
||||
{...field}
|
||||
type="number"
|
||||
min={1}
|
||||
value={field.value}
|
||||
value={field.value ?? ""}
|
||||
placeholder={`Default: ${organization?.max_steps_per_run ?? MAX_STEPS_DEFAULT}`}
|
||||
onChange={(event) => {
|
||||
field.onChange(parseInt(event.target.value));
|
||||
const value =
|
||||
event.target.value === ""
|
||||
? null
|
||||
: Number(event.target.value);
|
||||
field.onChange(value);
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
@@ -630,8 +649,8 @@ function SavedTaskForm({ initialValues }: Props) {
|
||||
<div className="w-full">
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder="https://"
|
||||
{...field}
|
||||
placeholder="https://"
|
||||
value={field.value === null ? "" : field.value}
|
||||
/>
|
||||
</FormControl>
|
||||
@@ -689,8 +708,8 @@ function SavedTaskForm({ initialValues }: Props) {
|
||||
<div className="w-full">
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder="https://"
|
||||
{...field}
|
||||
placeholder="Provide your 2FA endpoint"
|
||||
value={field.value === null ? "" : field.value}
|
||||
/>
|
||||
</FormControl>
|
||||
@@ -715,8 +734,8 @@ function SavedTaskForm({ initialValues }: Props) {
|
||||
<div className="w-full">
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder="Idenfitifer"
|
||||
{...field}
|
||||
placeholder="Add an ID that links your TOTP to the task"
|
||||
value={field.value === null ? "" : field.value}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
@@ -9,7 +9,7 @@ const createNewTaskFormSchemaBase = z.object({
|
||||
dataExtractionGoal: z.string().or(z.null()),
|
||||
navigationPayload: z.string().or(z.null()),
|
||||
extractedInformationSchema: z.string().or(z.null()),
|
||||
maxStepsOverride: z.number().optional(),
|
||||
maxStepsOverride: z.number().or(z.null()).optional(),
|
||||
totpVerificationUrl: z.string().or(z.null()),
|
||||
totpIdentifier: z.string().or(z.null()),
|
||||
errorCodeMapping: z.string().or(z.null()),
|
||||
|
||||
@@ -55,7 +55,7 @@ function DownloadNode({ id, data }: NodeProps<DownloadNode>) {
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-1">
|
||||
<Label className="text-sm text-slate-400">File URL</Label>
|
||||
<Input value={data.url} disabled className="nopan" />
|
||||
<Input value={data.url} disabled className="nopan text-xs" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -68,7 +68,7 @@ function FileParserNode({ id, data }: NodeProps<FileParserNode>) {
|
||||
setInputs({ ...inputs, fileUrl: event.target.value });
|
||||
updateNodeData(id, { fileUrl: event.target.value });
|
||||
}}
|
||||
className="nopan"
|
||||
className="nopan text-xs"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -80,7 +80,7 @@ function SendEmailNode({ id, data }: NodeProps<SendEmailNode>) {
|
||||
}}
|
||||
value={inputs.recipients}
|
||||
placeholder="example@gmail.com, example2@gmail.com..."
|
||||
className="nopan"
|
||||
className="nopan text-xs"
|
||||
/>
|
||||
</div>
|
||||
<Separator />
|
||||
@@ -95,7 +95,7 @@ function SendEmailNode({ id, data }: NodeProps<SendEmailNode>) {
|
||||
}}
|
||||
value={inputs.subject}
|
||||
placeholder="What is the gist?"
|
||||
className="nopan"
|
||||
className="nopan text-xs"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
@@ -109,7 +109,7 @@ function SendEmailNode({ id, data }: NodeProps<SendEmailNode>) {
|
||||
}}
|
||||
value={inputs.body}
|
||||
placeholder="What would you like to say?"
|
||||
className="nopan"
|
||||
className="nopan text-xs"
|
||||
/>
|
||||
</div>
|
||||
<Separator />
|
||||
@@ -124,7 +124,7 @@ function SendEmailNode({ id, data }: NodeProps<SendEmailNode>) {
|
||||
handleChange("fileAttachments", event.target.value);
|
||||
}}
|
||||
disabled
|
||||
className="nopan"
|
||||
className="nopan text-xs"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -30,6 +30,9 @@ import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import { TaskNodeDisplayModeSwitch } from "./TaskNodeDisplayModeSwitch";
|
||||
import { TaskNodeParametersPanel } from "./TaskNodeParametersPanel";
|
||||
import {
|
||||
dataSchemaExampleValue,
|
||||
errorMappingExampleValue,
|
||||
fieldPlaceholders,
|
||||
helpTooltipContent,
|
||||
type TaskNode,
|
||||
type TaskNodeDisplayMode,
|
||||
@@ -90,7 +93,7 @@ function TaskNode({ id, data }: NodeProps<TaskNode>) {
|
||||
<Label className="text-xs text-slate-300">URL</Label>
|
||||
<AutoResizingTextarea
|
||||
value={inputs.url}
|
||||
className="nopan"
|
||||
className="nopan text-xs"
|
||||
name="url"
|
||||
onChange={(event) => {
|
||||
if (!editable) {
|
||||
@@ -98,7 +101,7 @@ function TaskNode({ id, data }: NodeProps<TaskNode>) {
|
||||
}
|
||||
handleChange("url", event.target.value);
|
||||
}}
|
||||
placeholder="https://"
|
||||
placeholder={fieldPlaceholders["url"]}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
@@ -111,8 +114,8 @@ function TaskNode({ id, data }: NodeProps<TaskNode>) {
|
||||
handleChange("navigationGoal", event.target.value);
|
||||
}}
|
||||
value={inputs.navigationGoal}
|
||||
placeholder="What are you looking to do?"
|
||||
className="nopan"
|
||||
placeholder={fieldPlaceholders["navigationGoal"]}
|
||||
className="nopan text-xs"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
@@ -151,8 +154,8 @@ function TaskNode({ id, data }: NodeProps<TaskNode>) {
|
||||
handleChange("url", event.target.value);
|
||||
}}
|
||||
value={inputs.url}
|
||||
placeholder="https://"
|
||||
className="nopan"
|
||||
placeholder={fieldPlaceholders["url"]}
|
||||
className="nopan text-xs"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
@@ -165,8 +168,8 @@ function TaskNode({ id, data }: NodeProps<TaskNode>) {
|
||||
handleChange("navigationGoal", event.target.value);
|
||||
}}
|
||||
value={inputs.navigationGoal}
|
||||
placeholder="What are you looking to do?"
|
||||
className="nopan"
|
||||
placeholder={fieldPlaceholders["navigationGoal"]}
|
||||
className="nopan text-xs"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
@@ -204,8 +207,8 @@ function TaskNode({ id, data }: NodeProps<TaskNode>) {
|
||||
handleChange("dataExtractionGoal", event.target.value);
|
||||
}}
|
||||
value={inputs.dataExtractionGoal}
|
||||
placeholder="What outputs are you looking to get?"
|
||||
className="nopan"
|
||||
placeholder={fieldPlaceholders["dataExtractionGoal"]}
|
||||
className="nopan text-xs"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
@@ -217,7 +220,12 @@ function TaskNode({ id, data }: NodeProps<TaskNode>) {
|
||||
if (!editable) {
|
||||
return;
|
||||
}
|
||||
handleChange("dataSchema", checked ? "{}" : "null");
|
||||
handleChange(
|
||||
"dataSchema",
|
||||
checked
|
||||
? JSON.stringify(dataSchemaExampleValue, null, 2)
|
||||
: "null",
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -257,15 +265,19 @@ function TaskNode({ id, data }: NodeProps<TaskNode>) {
|
||||
</Label>
|
||||
<Input
|
||||
type="number"
|
||||
placeholder="0"
|
||||
className="nopan w-44"
|
||||
placeholder={fieldPlaceholders["maxRetries"]}
|
||||
className="nopan w-44 text-xs"
|
||||
min="0"
|
||||
value={inputs.maxRetries ?? 0}
|
||||
value={inputs.maxRetries ?? ""}
|
||||
onChange={(event) => {
|
||||
if (!editable) {
|
||||
return;
|
||||
}
|
||||
handleChange("maxRetries", Number(event.target.value));
|
||||
const value =
|
||||
event.target.value === ""
|
||||
? null
|
||||
: Number(event.target.value);
|
||||
handleChange("maxRetries", value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -275,18 +287,19 @@ function TaskNode({ id, data }: NodeProps<TaskNode>) {
|
||||
</Label>
|
||||
<Input
|
||||
type="number"
|
||||
placeholder="0"
|
||||
className="nopan w-44"
|
||||
placeholder={fieldPlaceholders["maxStepsOverride"]}
|
||||
className="nopan w-44 text-xs"
|
||||
min="0"
|
||||
value={inputs.maxStepsOverride ?? 0}
|
||||
value={inputs.maxStepsOverride ?? ""}
|
||||
onChange={(event) => {
|
||||
if (!editable) {
|
||||
return;
|
||||
}
|
||||
handleChange(
|
||||
"maxStepsOverride",
|
||||
Number(event.target.value),
|
||||
);
|
||||
const value =
|
||||
event.target.value === ""
|
||||
? null
|
||||
: Number(event.target.value);
|
||||
handleChange("maxStepsOverride", value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -308,12 +321,12 @@ function TaskNode({ id, data }: NodeProps<TaskNode>) {
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<Label className="text-xs font-normal text-slate-300">
|
||||
Download Suffix
|
||||
File Suffix
|
||||
</Label>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Suffix"
|
||||
className="nopan w-44"
|
||||
placeholder={fieldPlaceholders["downloadSuffix"]}
|
||||
className="nopan w-44 text-xs"
|
||||
value={inputs.downloadSuffix ?? ""}
|
||||
onChange={(event) => {
|
||||
if (!editable) {
|
||||
@@ -335,7 +348,12 @@ function TaskNode({ id, data }: NodeProps<TaskNode>) {
|
||||
if (!editable) {
|
||||
return;
|
||||
}
|
||||
handleChange("errorCodeMapping", checked ? "{}" : "null");
|
||||
handleChange(
|
||||
"errorCodeMapping",
|
||||
checked
|
||||
? JSON.stringify(errorMappingExampleValue, null, 2)
|
||||
: "null",
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -381,8 +399,8 @@ function TaskNode({ id, data }: NodeProps<TaskNode>) {
|
||||
handleChange("totpVerificationUrl", event.target.value);
|
||||
}}
|
||||
value={inputs.totpVerificationUrl ?? ""}
|
||||
placeholder="Link your 2FA storage endpoint"
|
||||
className="nopan"
|
||||
placeholder={fieldPlaceholders["totpVerificationUrl"]}
|
||||
className="nopan text-xs"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
@@ -397,8 +415,8 @@ function TaskNode({ id, data }: NodeProps<TaskNode>) {
|
||||
handleChange("totpIdentifier", event.target.value);
|
||||
}}
|
||||
value={inputs.totpIdentifier ?? ""}
|
||||
placeholder="Add an ID that links your TOTP to the task"
|
||||
className="nopan"
|
||||
placeholder={fieldPlaceholders["totpIdentifier"]}
|
||||
className="nopan text-xs"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -41,6 +41,7 @@ export const taskNodeDefaultData: TaskNodeData = {
|
||||
export function isTaskNode(node: Node): node is TaskNode {
|
||||
return node.type === "task";
|
||||
}
|
||||
|
||||
export const helpTooltipContent = {
|
||||
base: "Tell Skyvern what to do. This is the core of your task block, so make sure your prompt tells Skyvern when it has completed its task, any guardrails, and if there are cases where it should terminate the task early. Define placeholder values using the “parameters” drop down that you predefine or redefine run-to-run. This allows you to make a workflow generalizable to a variety of use cases that change with every run.",
|
||||
extraction:
|
||||
@@ -48,4 +49,27 @@ export const helpTooltipContent = {
|
||||
limits:
|
||||
"Give Skyvern limitations, such as number of retries on failure, the number of maximum steps, the option to download and append suffix identifiers, and return message for errors Skyvern encounters.",
|
||||
totp: "Link your internal TOTP storage system to relay 2FA codes we encounter straight to Skyvern. If you have multiple tasks running simultaneously, make sure to link an identifier so Skyvern knows which TOTP URL goes with which task.",
|
||||
} as const;
|
||||
|
||||
export const fieldPlaceholders = {
|
||||
url: "https://",
|
||||
navigationGoal: "Tell Skyvern what to do.",
|
||||
dataExtractionGoal: "What data do you need to extract?",
|
||||
maxRetries: "Default: 3",
|
||||
maxStepsOverride: "Default: 10",
|
||||
downloadSuffix: "Suffix for file downloads",
|
||||
label: "Task",
|
||||
totpVerificationUrl: "Provide your 2FA endpoint",
|
||||
totpIdentifier: "Add an ID that links your TOTP to the task",
|
||||
};
|
||||
|
||||
export const errorMappingExampleValue = {
|
||||
sample_invalid_credentials: "if the credentials are incorrect, terminate",
|
||||
};
|
||||
|
||||
export const dataSchemaExampleValue = {
|
||||
type: "object",
|
||||
properties: {
|
||||
sample: { type: "string" },
|
||||
},
|
||||
};
|
||||
|
||||
@@ -75,7 +75,7 @@ function TextPromptNode({ id, data }: NodeProps<TextPromptNode>) {
|
||||
}}
|
||||
value={inputs.prompt}
|
||||
placeholder="What do you want to generate?"
|
||||
className="nopan"
|
||||
className="nopan text-xs"
|
||||
/>
|
||||
</div>
|
||||
<Separator />
|
||||
|
||||
@@ -55,7 +55,7 @@ function UploadNode({ id, data }: NodeProps<UploadNode>) {
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-1">
|
||||
<Label className="text-sm text-slate-400">File Path</Label>
|
||||
<Input value={data.path} className="nopan" disabled />
|
||||
<Input value={data.path} className="nopan text-xs" disabled />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user