-
-
- {[prompt.metadata?.category, prompt.name]
- .filter(Boolean)
- .join(" - ")}
-
- {": "}
- Tool Call requires authentication
-
-
- {prompt.metadata.authType === "oauth" && (
+
{getMessage()}
+
+ {prompt.metadata?.authURL && (
setIsSubmitted(true)}
to={prompt.metadata.authURL}
>
- Authenticate with {prompt.metadata.category}
+
+ {getCtaText()}
)}
- {prompt.metadata.authType === "basic" && prompt.fields && (
+ {prompt.fields && (
@@ -242,7 +272,7 @@ function PromptAuthForm({
control={form.control}
name={field}
label={field}
- type={field.includes("password") ? "password" : "text"}
+ type={prompt.sensitive ? "password" : "text"}
/>
))}
@@ -251,7 +281,7 @@ function PromptAuthForm({
loading={authenticate.isLoading}
type="submit"
>
- Authenticate
+ Submit
diff --git a/ui/admin/app/components/workflow/Workflow.tsx b/ui/admin/app/components/workflow/Workflow.tsx
index da65a49a..baf56090 100644
--- a/ui/admin/app/components/workflow/Workflow.tsx
+++ b/ui/admin/app/components/workflow/Workflow.tsx
@@ -2,6 +2,7 @@ import {
KeyIcon,
Library,
List,
+ LockIcon,
PuzzleIcon,
Variable,
WrenchIcon,
@@ -9,12 +10,14 @@ import {
import { useCallback, useState } from "react";
import { Workflow as WorkflowType } from "~/lib/model/workflows";
+import { WorkflowService } from "~/lib/service/api/workflowService";
import { cn } from "~/lib/utils";
import { TypographyH4, TypographyP } from "~/components/Typography";
import { AgentForm } from "~/components/agent";
import { AgentKnowledgePanel } from "~/components/knowledge";
import { BasicToolForm } from "~/components/tools/BasicToolForm";
+import { Button } from "~/components/ui/button";
import { CardDescription } from "~/components/ui/card";
import { ScrollArea } from "~/components/ui/scroll-area";
import { ParamsForm } from "~/components/workflow/ParamsForm";
@@ -25,10 +28,12 @@ import {
} from "~/components/workflow/WorkflowContext";
import { WorkflowEnvForm } from "~/components/workflow/WorkflowEnvForm";
import { StepsForm } from "~/components/workflow/steps/StepsForm";
+import { useAsync } from "~/hooks/useAsync";
import { useDebounce } from "~/hooks/useDebounce";
type WorkflowProps = {
workflow: WorkflowType;
+ onPersistThreadId: (threadId: string) => void;
className?: string;
};
@@ -40,7 +45,7 @@ export function Workflow(props: WorkflowProps) {
);
}
-function WorkflowContent({ className }: WorkflowProps) {
+function WorkflowContent({ className, onPersistThreadId }: WorkflowProps) {
const { workflow, updateWorkflow, isUpdating, lastUpdated } = useWorkflow();
const [workflowUpdates, setWorkflowUpdates] = useState(workflow);
@@ -62,6 +67,10 @@ function WorkflowContent({ className }: WorkflowProps) {
const debouncedSetWorkflowInfo = useDebounce(partialSetWorkflow, 1000);
+ const authenticate = useAsync(WorkflowService.authenticateWorkflow, {
+ onSuccess: ({ threadId }) => onPersistThreadId(threadId),
+ });
+
return (
@@ -168,7 +177,7 @@ function WorkflowContent({ className }: WorkflowProps) {
-
);
diff --git a/ui/admin/app/lib/model/chatEvents.ts b/ui/admin/app/lib/model/chatEvents.ts
index 2ac485d7..1722137e 100644
--- a/ui/admin/app/lib/model/chatEvents.ts
+++ b/ui/admin/app/lib/model/chatEvents.ts
@@ -13,20 +13,13 @@ export type ToolCall = {
};
};
-type PromptAuthMetaBase = {
- category: string;
- icon: string;
- toolContext: string;
- toolDisplayName: string;
-};
-
-type PromptOAuthMeta = PromptAuthMetaBase & {
- authType: "oauth";
- authURL: string;
-};
-
-type PromptAuthBasicMeta = PromptAuthMetaBase & {
- authType: "basic";
+type PromptAuthMeta = {
+ authURL?: string;
+ category?: string;
+ icon?: string;
+ toolContext?: string;
+ toolDisplayName?: string;
+ authType: "oauth" | "basic";
};
export type AuthPrompt = {
@@ -36,7 +29,7 @@ export type AuthPrompt = {
message: string;
fields?: string[];
sensitive?: boolean;
- metadata?: PromptOAuthMeta | PromptAuthBasicMeta;
+ metadata?: PromptAuthMeta;
};
// note(ryanhopperlowe) renaming this to ChatEvent to differentiate itself specifically for a chat with an agent
diff --git a/ui/admin/app/lib/routers/apiRoutes.ts b/ui/admin/app/lib/routers/apiRoutes.ts
index 7f3e08b9..ae2d1b6a 100644
--- a/ui/admin/app/lib/routers/apiRoutes.ts
+++ b/ui/admin/app/lib/routers/apiRoutes.ts
@@ -109,6 +109,8 @@ export const ApiRoutes = {
buildUrl(`/workflows/${workflowId}/files/${fileName}`),
deleteKnowledge: (workflowId: string, fileName: string) =>
buildUrl(`/workflows/${workflowId}/files/${fileName}`),
+ authenticate: (workflowId: string) =>
+ buildUrl(`/workflows/${workflowId}/authenticate`),
},
threads: {
base: () => buildUrl("/threads"),
diff --git a/ui/admin/app/lib/service/api/workflowService.ts b/ui/admin/app/lib/service/api/workflowService.ts
index 3420ca65..deaa5f24 100644
--- a/ui/admin/app/lib/service/api/workflowService.ts
+++ b/ui/admin/app/lib/service/api/workflowService.ts
@@ -4,7 +4,7 @@ import {
Workflow,
} from "~/lib/model/workflows";
import { ApiRoutes, revalidateWhere } from "~/lib/routers/apiRoutes";
-import { request } from "~/lib/service/api/primitives";
+import { ResponseHeaders, request } from "~/lib/service/api/primitives";
async function getWorkflows() {
const res = await request<{ items: Workflow[] }>({
@@ -69,6 +69,24 @@ async function deleteWorkflow(id: string) {
const revalidateWorkflows = () =>
revalidateWhere((url) => url.includes(ApiRoutes.workflows.base().path));
+async function authenticateWorkflow(workflowId: string) {
+ const response = await request