Update Copy to cURL buttons to reference the new Runs API spec (#3765)
Co-authored-by: Shuchang Zheng <wintonzheng0325@gmail.com>
This commit is contained in:
@@ -21,9 +21,10 @@ import { KeyValueInput } from "@/components/KeyValueInput";
|
||||
import { useApiCredential } from "@/hooks/useApiCredential";
|
||||
import { useCredentialGetter } from "@/hooks/useCredentialGetter";
|
||||
import { CodeEditor } from "@/routes/workflows/components/CodeEditor";
|
||||
import { apiBaseUrl } from "@/util/env";
|
||||
import { runsApiBaseUrl } from "@/util/env";
|
||||
import { CopyApiCommandDropdown } from "@/components/CopyApiCommandDropdown";
|
||||
import { type ApiCommandOptions } from "@/util/apiCommands";
|
||||
import { buildTaskRunPayload } from "@/util/taskRunPayload";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { PlayIcon, ReloadIcon } from "@radix-ui/react-icons";
|
||||
import { ToastAction } from "@radix-ui/react-toast";
|
||||
@@ -754,17 +755,30 @@ function CreateNewTaskForm({ initialValues }: Props) {
|
||||
|
||||
<div className="flex justify-end gap-3">
|
||||
<CopyApiCommandDropdown
|
||||
getOptions={() =>
|
||||
({
|
||||
getOptions={() => {
|
||||
const formValues = form.getValues();
|
||||
const includeOverrideHeader =
|
||||
formValues.maxStepsOverride !== null &&
|
||||
formValues.maxStepsOverride !== MAX_STEPS_DEFAULT;
|
||||
|
||||
const headers: Record<string, string> = {
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": apiCredential ?? "<your-api-key>",
|
||||
};
|
||||
|
||||
if (includeOverrideHeader) {
|
||||
headers["x-max-steps-override"] = String(
|
||||
formValues.maxStepsOverride,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
method: "POST",
|
||||
url: `${apiBaseUrl}/tasks`,
|
||||
body: createTaskRequestObject(form.getValues()),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": apiCredential ?? "<your-api-key>",
|
||||
},
|
||||
}) satisfies ApiCommandOptions
|
||||
}
|
||||
url: `${runsApiBaseUrl}/run/tasks`,
|
||||
body: buildTaskRunPayload(createTaskRequestObject(formValues)),
|
||||
headers,
|
||||
} satisfies ApiCommandOptions;
|
||||
}}
|
||||
/>
|
||||
<Button type="submit" disabled={mutation.isPending}>
|
||||
{mutation.isPending && (
|
||||
|
||||
@@ -16,9 +16,10 @@ import { useApiCredential } from "@/hooks/useApiCredential";
|
||||
import { useCredentialGetter } from "@/hooks/useCredentialGetter";
|
||||
import { CodeEditor } from "@/routes/workflows/components/CodeEditor";
|
||||
import { SubmitEvent } from "@/types";
|
||||
import { apiBaseUrl } from "@/util/env";
|
||||
import { runsApiBaseUrl } from "@/util/env";
|
||||
import { CopyApiCommandDropdown } from "@/components/CopyApiCommandDropdown";
|
||||
import { type ApiCommandOptions } from "@/util/apiCommands";
|
||||
import { buildTaskRunPayload } from "@/util/taskRunPayload";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { PlayIcon, ReloadIcon } from "@radix-ui/react-icons";
|
||||
import { ToastAction } from "@radix-ui/react-toast";
|
||||
@@ -31,7 +32,11 @@ import { stringify as convertToYAML } from "yaml";
|
||||
import { MAX_STEPS_DEFAULT } from "../constants";
|
||||
import { TaskFormSection } from "./TaskFormSection";
|
||||
import { savedTaskFormSchema, SavedTaskFormValues } from "./taskFormTypes";
|
||||
import { OrganizationApiResponse, ProxyLocation } from "@/api/types";
|
||||
import {
|
||||
CreateTaskRequest,
|
||||
OrganizationApiResponse,
|
||||
ProxyLocation,
|
||||
} from "@/api/types";
|
||||
import { ProxySelector } from "@/components/ProxySelector";
|
||||
import { TestWebhookDialog } from "@/components/TestWebhookDialog";
|
||||
|
||||
@@ -39,11 +44,13 @@ type Props = {
|
||||
initialValues: SavedTaskFormValues;
|
||||
};
|
||||
|
||||
function transform(value: unknown) {
|
||||
function transform<T>(value: T): T | null {
|
||||
return value === "" ? null : value;
|
||||
}
|
||||
|
||||
function createTaskRequestObject(formValues: SavedTaskFormValues) {
|
||||
function createTaskRequestObject(
|
||||
formValues: SavedTaskFormValues,
|
||||
): CreateTaskRequest {
|
||||
return {
|
||||
title: formValues.title,
|
||||
url: formValues.url,
|
||||
@@ -759,17 +766,30 @@ function SavedTaskForm({ initialValues }: Props) {
|
||||
|
||||
<div className="flex justify-end gap-3">
|
||||
<CopyApiCommandDropdown
|
||||
getOptions={() =>
|
||||
({
|
||||
getOptions={() => {
|
||||
const formValues = form.getValues();
|
||||
const includeOverrideHeader =
|
||||
formValues.maxStepsOverride !== null &&
|
||||
formValues.maxStepsOverride !== MAX_STEPS_DEFAULT;
|
||||
|
||||
const headers: Record<string, string> = {
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": apiCredential ?? "<your-api-key>",
|
||||
};
|
||||
|
||||
if (includeOverrideHeader) {
|
||||
headers["x-max-steps-override"] = String(
|
||||
formValues.maxStepsOverride,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
method: "POST",
|
||||
url: `${apiBaseUrl}/tasks`,
|
||||
body: createTaskRequestObject(form.getValues()),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": apiCredential ?? "<your-api-key>",
|
||||
},
|
||||
}) satisfies ApiCommandOptions
|
||||
}
|
||||
url: `${runsApiBaseUrl}/run/tasks`,
|
||||
body: buildTaskRunPayload(createTaskRequestObject(formValues)),
|
||||
headers,
|
||||
} satisfies ApiCommandOptions;
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
|
||||
@@ -25,14 +25,16 @@ import { useApiCredential } from "@/hooks/useApiCredential";
|
||||
import { useCredentialGetter } from "@/hooks/useCredentialGetter";
|
||||
import { CodeEditor } from "@/routes/workflows/components/CodeEditor";
|
||||
import { WorkflowApiResponse } from "@/routes/workflows/types/workflowTypes";
|
||||
import { apiBaseUrl } from "@/util/env";
|
||||
import { runsApiBaseUrl } from "@/util/env";
|
||||
import { ApiWebhookActionsMenu } from "@/components/ApiWebhookActionsMenu";
|
||||
import { WebhookReplayDialog } from "@/components/WebhookReplayDialog";
|
||||
import { type ApiCommandOptions } from "@/util/apiCommands";
|
||||
import { buildTaskRunPayload } from "@/util/taskRunPayload";
|
||||
import { PlayIcon, ReloadIcon } from "@radix-ui/react-icons";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { Link, Outlet, useParams } from "react-router-dom";
|
||||
import { statusIsFinalized } from "../types";
|
||||
import { MAX_STEPS_DEFAULT } from "../constants";
|
||||
import { useTaskQuery } from "./hooks/useTaskQuery";
|
||||
|
||||
function createTaskRequestObject(values: TaskApiResponse) {
|
||||
@@ -206,14 +208,27 @@ function TaskDetails() {
|
||||
},
|
||||
} satisfies ApiCommandOptions;
|
||||
}
|
||||
|
||||
const includeOverrideHeader =
|
||||
task.max_steps_per_run !== null &&
|
||||
task.max_steps_per_run !== MAX_STEPS_DEFAULT;
|
||||
|
||||
const headers: Record<string, string> = {
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": apiCredential ?? "<your-api-key>",
|
||||
};
|
||||
|
||||
if (includeOverrideHeader) {
|
||||
headers["x-max-steps-override"] = String(
|
||||
task.max_steps_per_run,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
method: "POST",
|
||||
url: `${apiBaseUrl}/tasks`,
|
||||
body: createTaskRequestObject(task),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": apiCredential ?? "<your-api-key>",
|
||||
},
|
||||
url: `${runsApiBaseUrl}/run/tasks`,
|
||||
body: buildTaskRunPayload(createTaskRequestObject(task)),
|
||||
headers,
|
||||
} satisfies ApiCommandOptions;
|
||||
}}
|
||||
webhookDisabled={taskIsLoading || !taskHasTerminalState}
|
||||
|
||||
@@ -42,7 +42,7 @@ import { useBlockScriptsQuery } from "@/routes/workflows/hooks/useBlockScriptsQu
|
||||
import { constructCacheKeyValueFromParameters } from "@/routes/workflows/editor/utils";
|
||||
import { useWorkflowQuery } from "@/routes/workflows/hooks/useWorkflowQuery";
|
||||
import { type ApiCommandOptions } from "@/util/apiCommands";
|
||||
import { apiBaseUrl } from "@/util/env";
|
||||
import { runsApiBaseUrl } from "@/util/env";
|
||||
|
||||
import { MAX_SCREENSHOT_SCROLLS_DEFAULT } from "./editor/nodes/Taskv2Node/types";
|
||||
import { getLabelForWorkflowParameterType } from "./editor/workflowEditorUtils";
|
||||
@@ -167,6 +167,25 @@ function getRunWorkflowRequestBody(
|
||||
return body;
|
||||
}
|
||||
|
||||
// Transform RunWorkflowRequestBody to match WorkflowRunRequest schema for Runs API v2
|
||||
function transformToWorkflowRunRequest(
|
||||
body: RunWorkflowRequestBody,
|
||||
workflowId: string,
|
||||
) {
|
||||
const { data, webhook_callback_url, ...rest } = body;
|
||||
const transformed: Record<string, unknown> = {
|
||||
workflow_id: workflowId,
|
||||
parameters: data,
|
||||
...rest,
|
||||
};
|
||||
|
||||
if (webhook_callback_url) {
|
||||
transformed.webhook_url = webhook_callback_url;
|
||||
}
|
||||
|
||||
return transformed;
|
||||
}
|
||||
|
||||
type RunWorkflowFormType = Record<string, unknown> & {
|
||||
webhookCallbackUrl: string;
|
||||
proxyLocation: ProxyLocation;
|
||||
@@ -807,14 +826,22 @@ function RunWorkflowForm({
|
||||
values,
|
||||
workflowParameters,
|
||||
);
|
||||
const transformedBody = transformToWorkflowRunRequest(
|
||||
body,
|
||||
workflowPermanentId,
|
||||
);
|
||||
|
||||
// Build headers - x-max-steps-override is optional and can be added manually if needed
|
||||
const headers: Record<string, string> = {
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": apiCredential ?? "<your-api-key>",
|
||||
};
|
||||
|
||||
return {
|
||||
method: "POST",
|
||||
url: `${apiBaseUrl}/workflows/${workflowPermanentId}/run`,
|
||||
body,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": apiCredential ?? "<your-api-key>",
|
||||
},
|
||||
url: `${runsApiBaseUrl}/run/workflows`,
|
||||
body: transformedBody,
|
||||
headers,
|
||||
} satisfies ApiCommandOptions;
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -21,7 +21,7 @@ import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { toast } from "@/components/ui/use-toast";
|
||||
import { useApiCredential } from "@/hooks/useApiCredential";
|
||||
import { useCredentialGetter } from "@/hooks/useCredentialGetter";
|
||||
import { apiBaseUrl } from "@/util/env";
|
||||
import { runsApiBaseUrl } from "@/util/env";
|
||||
import {
|
||||
CodeIcon,
|
||||
FileIcon,
|
||||
@@ -312,20 +312,34 @@ function WorkflowRun() {
|
||||
|
||||
<div className="flex gap-2">
|
||||
<ApiWebhookActionsMenu
|
||||
getOptions={() =>
|
||||
({
|
||||
getOptions={() => {
|
||||
// Build headers - x-max-steps-override is optional and can be added manually if needed
|
||||
const headers: Record<string, string> = {
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": apiCredential ?? "<your-api-key>",
|
||||
};
|
||||
|
||||
const body: Record<string, unknown> = {
|
||||
workflow_id: workflowPermanentId,
|
||||
parameters: workflowRun?.parameters,
|
||||
proxy_location: proxyLocation,
|
||||
};
|
||||
|
||||
if (maxScreenshotScrolls !== null) {
|
||||
body.max_screenshot_scrolls = maxScreenshotScrolls;
|
||||
}
|
||||
|
||||
if (workflowRun?.webhook_callback_url) {
|
||||
body.webhook_url = workflowRun.webhook_callback_url;
|
||||
}
|
||||
|
||||
return {
|
||||
method: "POST",
|
||||
url: `${apiBaseUrl}/workflows/${workflowPermanentId}/run`,
|
||||
body: {
|
||||
data: workflowRun?.parameters,
|
||||
proxy_location: "RESIDENTIAL",
|
||||
},
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": apiCredential ?? "<your-api-key>",
|
||||
},
|
||||
}) satisfies ApiCommandOptions
|
||||
}
|
||||
url: `${runsApiBaseUrl}/run/workflows`,
|
||||
body,
|
||||
headers,
|
||||
} satisfies ApiCommandOptions;
|
||||
}}
|
||||
webhookDisabled={workflowRunIsLoading || !workflowRunIsFinalized}
|
||||
onTestWebhook={() => setReplayOpen(true)}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user