mirror of
https://github.com/Skyvern-AI/skyvern.git
synced 2026-07-09 16:09:13 +00:00
[SKY-8863] Address spillover (#5457)
This commit is contained in:
parent
8c13eca7ee
commit
9c945ee480
10 changed files with 77 additions and 39 deletions
|
|
@ -58,7 +58,7 @@ tabs:
|
||||||
demo:
|
demo:
|
||||||
display-name: Book a demo
|
display-name: Book a demo
|
||||||
icon: calendar
|
icon: calendar
|
||||||
href: https://meetings.hubspot.com/skyvern/demo
|
href: https://www.skyvern.com/contact
|
||||||
navigation:
|
navigation:
|
||||||
- tab: home
|
- tab: home
|
||||||
layout:
|
layout:
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ To read about specific blocks, check out [the block documentation](/workflows/wo
|
||||||
|
|
||||||
|
|
||||||
## Managing Credentials and Sensitive Information
|
## Managing Credentials and Sensitive Information
|
||||||
This is something the Skyvern team will need to set you up with today. If you're interested, please [book a call with Suchintan](https://meetings.hubspot.com/skyvern/demo)
|
This is something the Skyvern team will need to set you up with today. If you're interested, please [book a call with Suchintan](https://www.skyvern.com/contact)
|
||||||
|
|
||||||
|
|
||||||
## Common concepts
|
## Common concepts
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ Inputs:
|
||||||
6. **Max Retries *(optional):*** the number of times a step can be retried if it fails
|
6. **Max Retries *(optional):*** the number of times a step can be retried if it fails
|
||||||
7. **Complete on Download *(optional):*** Allows Skyvern to complete the task after a file has been downloaded
|
7. **Complete on Download *(optional):*** Allows Skyvern to complete the task after a file has been downloaded
|
||||||
8. **File Suffix *(optional):*** an identifier attached to the downloaded file
|
8. **File Suffix *(optional):*** an identifier attached to the downloaded file
|
||||||
9. **TOTP URL and TOTP Identifier *(optional):*** if you have an internal system where you can store the 2FA TOTP code, this URL calls on this storage space. The identifier allows you to link the code to the task, this is critical if you are running multiple tasks concurrently. [Contact us](https://meetings.hubspot.com/skyvern/demo?uuid=7c83865f-1a92-4c44-9e52-1ba0dbc04f7a) if you would like to set up 2FA retreival in your workflows.
|
9. **TOTP URL and TOTP Identifier *(optional):*** if you have an internal system where you can store the 2FA TOTP code, this URL calls on this storage space. The identifier allows you to link the code to the task, this is critical if you are running multiple tasks concurrently. [Contact us](https://www.skyvern.com/contact)
|
||||||
10. **Parameters *(optional):*** parameters are self-defined placeholders that are specified run-to-run. They can either be workflow parameters, passed in via an API call, or output parameters, extracted from a previous task block. If specified, they are used by Skyvern to assist in the navigation, to fill out forms or further influence what actions to take on a website.
|
10. **Parameters *(optional):*** parameters are self-defined placeholders that are specified run-to-run. They can either be workflow parameters, passed in via an API call, or output parameters, extracted from a previous task block. If specified, they are used by Skyvern to assist in the navigation, to fill out forms or further influence what actions to take on a website.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -78,7 +78,7 @@ Iterate over something such as a CSV or the output of a previous block. The bloc
|
||||||
Inputs:
|
Inputs:
|
||||||
|
|
||||||
1. **Loop Value *(required):*** This is the value that the loop will iterate over. For instance, if you have for every invoice ID, do X, invoice ID would be the value for this input.
|
1. **Loop Value *(required):*** This is the value that the loop will iterate over. For instance, if you have for every invoice ID, do X, invoice ID would be the value for this input.
|
||||||
* Please [contact us](https://meetings.hubspot.com/skyvern/demo?uuid=7c83865f-1a92-4c44-9e52-1ba0dbc04f7a) if you would like to add a loop block. Since we’re in beta, the loop value needs to be parameterized from the backend.
|
* Please [contact us](https://www.skyvern.com/contact)
|
||||||
2. **Another block nested within the loop (required)**
|
2. **Another block nested within the loop (required)**
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -222,7 +222,7 @@ Inputs:
|
||||||
|
|
||||||
1. **Recipients *(required):*** a list of people who will receive the email separated by commas
|
1. **Recipients *(required):*** a list of people who will receive the email separated by commas
|
||||||
2. **Subject/Body *(optional):*** the header and body of an email
|
2. **Subject/Body *(optional):*** the header and body of an email
|
||||||
3. **File attachments *(optional):*** since we’re still in beta, you will need to [contact us](https://meetings.hubspot.com/skyvern/demo?uuid=7c83865f-1a92-4c44-9e52-1ba0dbc04f7a) to upload attachments to the email
|
3. **File attachments *(optional):*** since we’re still in beta, you will need to [contact us](https://www.skyvern.com/contact)
|
||||||
|
|
||||||
## FileParserBlock
|
## FileParserBlock
|
||||||
|
|
||||||
|
|
@ -240,4 +240,4 @@ Downloads and parses a file to be used within other workflow blocks.
|
||||||
Inputs:
|
Inputs:
|
||||||
|
|
||||||
1. **File URL *(required):*** This block allows you to use CSV, TSV, Excel, and PDF files within your workflow.
|
1. **File URL *(required):*** This block allows you to use CSV, TSV, Excel, and PDF files within your workflow.
|
||||||
* Since we’re still in beta, you will need to [contact us](https://meetings.hubspot.com/skyvern/demo?uuid=7c83865f-1a92-4c44-9e52-1ba0dbc04f7a) to load a value into this block
|
* Since we’re still in beta, you will need to [contact us](https://www.skyvern.com/contact)
|
||||||
|
|
@ -360,7 +360,7 @@ function PasswordCredentialContent({
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-slate-400">
|
<p className="text-sm text-slate-400">
|
||||||
<Link
|
<Link
|
||||||
to="https://meetings.hubspot.com/skyvern/demo"
|
to="https://www.skyvern.com/contact"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="underline underline-offset-2"
|
className="underline underline-offset-2"
|
||||||
|
|
|
||||||
|
|
@ -556,10 +556,10 @@ function WorkflowRun() {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="flex h-[42rem] gap-6">
|
<div className="flex h-[42rem] gap-6">
|
||||||
<div className="w-2/3">
|
<div className="min-w-0 flex-[2]">
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</div>
|
</div>
|
||||||
<div className="w-1/3 min-w-0 overflow-hidden">
|
<div className="min-w-0 flex-1 overflow-hidden">
|
||||||
<WorkflowRunTimeline
|
<WorkflowRunTimeline
|
||||||
activeItem={selection}
|
activeItem={selection}
|
||||||
onActionItemSelected={(item) => {
|
onActionItemSelected={(item) => {
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ function WorkflowsBetaAlertCard() {
|
||||||
</Button>
|
</Button>
|
||||||
<Button asChild>
|
<Button asChild>
|
||||||
<a
|
<a
|
||||||
href="https://meetings.hubspot.com/skyvern/demo"
|
href="https://www.skyvern.com/contact"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,9 @@ function ActionCard({ action, onClick, active, index, cardClassName }: Props) {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-xs text-slate-400">{action.reasoning}</div>
|
<div className="break-words text-xs text-slate-400">
|
||||||
|
{action.reasoning}
|
||||||
|
</div>
|
||||||
{action.action_type === ActionTypes.InputText && (
|
{action.action_type === ActionTypes.InputText && (
|
||||||
<>
|
<>
|
||||||
<Separator />
|
<Separator />
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ function ThoughtCard({ thought, onClick, active, cardClassName }: Props) {
|
||||||
</StatusPill>
|
</StatusPill>
|
||||||
</div>
|
</div>
|
||||||
{(thought.answer || thought.thought) && (
|
{(thought.answer || thought.thought) && (
|
||||||
<div className="text-xs text-slate-400">
|
<div className="break-words text-xs text-slate-400">
|
||||||
{thought.answer || thought.thought}
|
{thought.answer || thought.thought}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ function WorkflowRunTimeline({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ScrollArea>
|
<ScrollArea>
|
||||||
<ScrollAreaViewport className="h-[37rem] max-h-[37rem] [&>div]:!overflow-x-hidden">
|
<ScrollAreaViewport className="h-[37rem] max-h-[37rem] [&>div]:!block [&>div]:!overflow-x-hidden">
|
||||||
<div className="space-y-4 p-1">
|
<div className="space-y-4 p-1">
|
||||||
{workflowRunIsNotFinalized && (
|
{workflowRunIsNotFinalized && (
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import {
|
||||||
ExternalLinkIcon,
|
ExternalLinkIcon,
|
||||||
ReloadIcon,
|
ReloadIcon,
|
||||||
} from "@radix-ui/react-icons";
|
} from "@radix-ui/react-icons";
|
||||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { useShimmerText } from "./useShimmerText";
|
import { useShimmerText } from "./useShimmerText";
|
||||||
|
|
||||||
|
|
@ -117,6 +117,51 @@ function truncateValue(value: string, maxLength = 120): string {
|
||||||
return `${collapsed.slice(0, maxLength - 3)}...`;
|
return `${collapsed.slice(0, maxLength - 3)}...`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a loop value with line-clamp-2. Shows a tooltip with the full
|
||||||
|
* value only when the CSS clamp actually truncates the visible text.
|
||||||
|
*/
|
||||||
|
function LoopValueCode({
|
||||||
|
collapsed,
|
||||||
|
fullValue,
|
||||||
|
}: {
|
||||||
|
collapsed: string;
|
||||||
|
fullValue: string;
|
||||||
|
}) {
|
||||||
|
const codeRef = useRef<HTMLElement>(null);
|
||||||
|
const [isClamped, setIsClamped] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const el = codeRef.current;
|
||||||
|
if (el) {
|
||||||
|
setIsClamped(el.scrollHeight > el.clientHeight + 1);
|
||||||
|
}
|
||||||
|
}, [collapsed]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TooltipProvider delayDuration={300}>
|
||||||
|
<Tooltip open={isClamped ? undefined : false}>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<code
|
||||||
|
ref={codeRef}
|
||||||
|
className="line-clamp-2 block min-w-0 break-all rounded bg-slate-elevation1 px-1 py-0.5 font-mono text-slate-300"
|
||||||
|
>
|
||||||
|
{collapsed}
|
||||||
|
</code>
|
||||||
|
</TooltipTrigger>
|
||||||
|
{isClamped && (
|
||||||
|
<TooltipContent
|
||||||
|
side="top"
|
||||||
|
className="max-w-xs break-all font-mono text-[11px]"
|
||||||
|
>
|
||||||
|
{fullValue}
|
||||||
|
</TooltipContent>
|
||||||
|
)}
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function getLoopIterationGroups(
|
function getLoopIterationGroups(
|
||||||
items: Array<WorkflowRunTimelineItem>,
|
items: Array<WorkflowRunTimelineItem>,
|
||||||
): Array<LoopIterationGroup> {
|
): Array<LoopIterationGroup> {
|
||||||
|
|
@ -440,7 +485,7 @@ function WorkflowRunTimelineBlockItem({
|
||||||
}}
|
}}
|
||||||
ref={refCallback}
|
ref={refCallback}
|
||||||
>
|
>
|
||||||
<div className="min-w-0 space-y-4 overflow-hidden p-4">
|
<div className="min-w-0 space-y-4 p-4">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<div className="flex gap-3">
|
<div className="flex gap-3">
|
||||||
|
|
@ -512,10 +557,12 @@ function WorkflowRunTimelineBlockItem({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{block.description ? (
|
{block.description ? (
|
||||||
<div className="text-xs text-slate-400">{block.description}</div>
|
<div className="break-words text-xs text-slate-400">
|
||||||
|
{block.description}
|
||||||
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
{isLoopBlock && (
|
{isLoopBlock && (
|
||||||
<div className="min-w-0 space-y-2 overflow-hidden rounded bg-slate-elevation5 px-3 py-2 text-xs">
|
<div className="min-w-0 space-y-2 rounded bg-slate-elevation5 px-3 py-2 text-xs">
|
||||||
<div className="text-slate-300">
|
<div className="text-slate-300">
|
||||||
Iterable values:{" "}
|
Iterable values:{" "}
|
||||||
<span className="font-medium text-slate-200">
|
<span className="font-medium text-slate-200">
|
||||||
|
|
@ -530,26 +577,15 @@ function WorkflowRunTimelineBlockItem({
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={index}
|
||||||
className="flex min-w-0 text-slate-400"
|
className="flex min-w-0 break-words text-slate-400"
|
||||||
>
|
>
|
||||||
<span className="mr-1 shrink-0 text-slate-500">
|
<span className="mr-1 shrink-0 text-slate-500">
|
||||||
[{index}]
|
[{index}]
|
||||||
</span>
|
</span>
|
||||||
<TooltipProvider delayDuration={300}>
|
<LoopValueCode
|
||||||
<Tooltip>
|
collapsed={collapsed}
|
||||||
<TooltipTrigger asChild>
|
fullValue={fullValue}
|
||||||
<code className="block min-w-0 truncate rounded bg-slate-elevation1 px-1 py-0.5 font-mono text-slate-300">
|
/>
|
||||||
{collapsed}
|
|
||||||
</code>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent
|
|
||||||
side="top"
|
|
||||||
className="max-w-xs break-all font-mono text-[11px]"
|
|
||||||
>
|
|
||||||
{fullValue}
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</TooltipProvider>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
@ -584,7 +620,7 @@ function WorkflowRunTimelineBlockItem({
|
||||||
) : (
|
) : (
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<div className="text-slate-400">
|
<div className="text-slate-400">
|
||||||
<code className="rounded bg-slate-elevation1 px-1 py-0.5 font-mono text-slate-300">
|
<code className="break-all rounded bg-slate-elevation1 px-1 py-0.5 font-mono text-slate-300">
|
||||||
{evaluation.original_expression}
|
{evaluation.original_expression}
|
||||||
</code>
|
</code>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -593,7 +629,7 @@ function WorkflowRunTimelineBlockItem({
|
||||||
evaluation.original_expression && (
|
evaluation.original_expression && (
|
||||||
<div className="text-slate-400">
|
<div className="text-slate-400">
|
||||||
→ rendered to{" "}
|
→ rendered to{" "}
|
||||||
<code className="rounded bg-slate-elevation1 px-1 py-0.5 font-mono text-slate-200">
|
<code className="break-all rounded bg-slate-elevation1 px-1 py-0.5 font-mono text-slate-200">
|
||||||
{evaluation.rendered_expression}
|
{evaluation.rendered_expression}
|
||||||
</code>
|
</code>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -637,7 +673,7 @@ function WorkflowRunTimelineBlockItem({
|
||||||
block.executed_branch_expression !== undefined ? (
|
block.executed_branch_expression !== undefined ? (
|
||||||
<div className="text-slate-300">
|
<div className="text-slate-300">
|
||||||
Condition{" "}
|
Condition{" "}
|
||||||
<code className="rounded bg-slate-elevation3 px-1.5 py-0.5 font-mono text-slate-200">
|
<code className="break-all rounded bg-slate-elevation3 px-1.5 py-0.5 font-mono text-slate-200">
|
||||||
{block.executed_branch_expression}
|
{block.executed_branch_expression}
|
||||||
</code>{" "}
|
</code>{" "}
|
||||||
evaluated to{" "}
|
evaluated to{" "}
|
||||||
|
|
@ -739,7 +775,7 @@ function WorkflowRunTimelineBlockItem({
|
||||||
<TooltipProvider delayDuration={300}>
|
<TooltipProvider delayDuration={300}>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<code className="max-w-[70%] truncate rounded bg-slate-elevation1 px-1 py-0.5 text-[11px] text-slate-300">
|
<code className="min-w-0 truncate rounded bg-slate-elevation1 px-1 py-0.5 text-[11px] text-slate-300">
|
||||||
current_value: {currentValuePreview}
|
current_value: {currentValuePreview}
|
||||||
</code>
|
</code>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
|
|
@ -752,14 +788,14 @@ function WorkflowRunTimelineBlockItem({
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
) : (
|
) : (
|
||||||
<code className="max-w-[70%] truncate rounded bg-slate-elevation1 px-1 py-0.5 text-[11px] text-slate-300">
|
<code className="min-w-0 truncate rounded bg-slate-elevation1 px-1 py-0.5 text-[11px] text-slate-300">
|
||||||
current_value: {currentValuePreview}
|
current_value: {currentValuePreview}
|
||||||
</code>
|
</code>
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</CollapsibleTrigger>
|
</CollapsibleTrigger>
|
||||||
</div>
|
</div>
|
||||||
<CollapsibleContent className="min-w-0 overflow-hidden px-2 pb-2 pt-2">
|
<CollapsibleContent className="min-w-0 px-2 pb-2 pt-2">
|
||||||
<TimelineSubItems
|
<TimelineSubItems
|
||||||
items={group.items}
|
items={group.items}
|
||||||
activeItem={activeItem}
|
activeItem={activeItem}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue