diff --git a/skyvern-frontend/src/routes/workflows/editor/WorkflowCopilotChat.tsx b/skyvern-frontend/src/routes/workflows/editor/WorkflowCopilotChat.tsx
index d8e23dfe..ecf22134 100644
--- a/skyvern-frontend/src/routes/workflows/editor/WorkflowCopilotChat.tsx
+++ b/skyvern-frontend/src/routes/workflows/editor/WorkflowCopilotChat.tsx
@@ -1,4 +1,4 @@
-import { useState, useEffect, useRef } from "react";
+import { useState, useEffect, useRef, memo } from "react";
import { getClient } from "@/api/AxiosClient";
import { useCredentialGetter } from "@/hooks/useCredentialGetter";
import { useIsSkyvernUser } from "@/hooks/useIsSkyvernUser";
@@ -16,6 +16,39 @@ interface ChatMessage {
timestamp?: string;
}
+const formatChatTimestamp = (value: string) => {
+ let normalizedValue = value.replace(/\.(\d{3})\d*/, ".$1");
+ if (!normalizedValue.endsWith("Z")) {
+ normalizedValue += "Z";
+ }
+ return new Date(normalizedValue).toLocaleTimeString("en-US", {
+ hour: "numeric",
+ minute: "2-digit",
+ });
+};
+
+const MessageItem = memo(({ message }: { message: ChatMessage }) => {
+ return (
+
(null);
const { getSaveData } = useWorkflowHasChangesStore();
const hasInitializedPosition = useRef(false);
-
- const formatChatTimestamp = (value: string) => {
- let normalizedValue = value.replace(/\.(\d{3})\d*/, ".$1");
- if (!normalizedValue.endsWith("Z")) {
- normalizedValue += "Z";
- }
- return new Date(normalizedValue).toLocaleTimeString("en-US", {
- hour: "numeric",
- minute: "2-digit",
- });
- };
-
const hasScrolledOnLoad = useRef(false);
const scrollToBottom = (behavior: ScrollBehavior) => {
@@ -296,13 +317,19 @@ export function WorkflowCopilotChat({
updated_workflow_yaml: string | null;
request_time: string;
response_time: string;
- }>("/workflow/copilot/chat-post", {
- workflow_permanent_id: workflowPermanentId,
- workflow_copilot_chat_id: workflowCopilotChatId,
- workflow_run_id: workflowRunId,
- message: messageContent,
- workflow_yaml: workflowYaml,
- });
+ }>(
+ "/workflow/copilot/chat-post",
+ {
+ workflow_permanent_id: workflowPermanentId,
+ workflow_copilot_chat_id: workflowCopilotChatId,
+ workflow_run_id: workflowRunId,
+ message: messageContent,
+ workflow_yaml: workflowYaml,
+ },
+ {
+ timeout: 300000,
+ },
+ );
setWorkflowCopilotChatId(response.data.workflow_copilot_chat_id);
@@ -343,10 +370,6 @@ export function WorkflowCopilotChat({
id: Date.now().toString(),
sender: "ai",
content: "Sorry, I encountered an error. Please try again.",
- timestamp: new Date().toLocaleTimeString("en-US", {
- hour: "numeric",
- minute: "2-digit",
- }),
};
setMessages((prev) => [...prev, errorMessage]);
} finally {
@@ -563,29 +586,13 @@ export function WorkflowCopilotChat({
the target site, and any credentials it should use.
- Example: “Build a workflow visit hackernews and get top 3 news
- items”
+ Example: "Build workflow to find the top post on hackernews
+ today"
) : null}
{messages.map((message) => (
-
-
- {message.sender === "ai" ? "AI" : "U"}
-
-
-
{message.content}
- {message.timestamp ? (
-
- {formatChatTimestamp(message.timestamp)}
-
- ) : null}
-
-
+
))}
{isLoading && (
diff --git a/skyvern-frontend/src/routes/workflows/editor/Workspace.tsx b/skyvern-frontend/src/routes/workflows/editor/Workspace.tsx
index c9362809..6f361410 100644
--- a/skyvern-frontend/src/routes/workflows/editor/Workspace.tsx
+++ b/skyvern-frontend/src/routes/workflows/editor/Workspace.tsx
@@ -1729,7 +1729,8 @@ function Workspace({
workflowChangesStore.setHasChanges(true);
} catch (error) {
- console.error("Failed to parse and apply workflow YAML:", error);
+ console.error("Failed to parse and apply workflow YAML", error);
+ console.log("YAML:", workflowYaml);
toast({
title: "Update failed",
description: "Failed to parse workflow YAML. Please try again.",
diff --git a/skyvern/forge/sdk/routes/workflow_copilot.py b/skyvern/forge/sdk/routes/workflow_copilot.py
index 0bc7f0a4..ee792068 100644
--- a/skyvern/forge/sdk/routes/workflow_copilot.py
+++ b/skyvern/forge/sdk/routes/workflow_copilot.py
@@ -1,3 +1,4 @@
+import time
from dataclasses import dataclass
from datetime import datetime, timezone
from pathlib import Path
@@ -103,14 +104,35 @@ async def copilot_call_llm(
)
LOG.info(
- "Calling LLM for workflow copilot",
- prompt_length=len(llm_prompt),
+ "Calling LLM",
+ user_message=chat_request.message,
+ user_message_len=len(chat_request.message),
+ workflow_yaml_len=len(chat_request.workflow_yaml or ""),
+ chat_history_len=len(chat_history_text),
+ global_llm_context_len=len(global_llm_context or ""),
+ debug_run_info_len=len(debug_run_info_text),
+ workflow_knowledge_base_len=len(workflow_knowledge_base),
+ llm_prompt_len=len(llm_prompt),
+ llm_prompt=llm_prompt,
)
+ llm_start_time = time.monotonic()
llm_response = await app.LLM_API_HANDLER(
prompt=llm_prompt,
prompt_name="workflow-copilot",
organization_id=organization_id,
)
+ LOG.info(
+ "LLM response",
+ duration_seconds=time.monotonic() - llm_start_time,
+ user_message_len=len(chat_request.message),
+ workflow_yaml_len=len(chat_request.workflow_yaml or ""),
+ chat_history_len=len(chat_history_text),
+ global_llm_context_len=len(global_llm_context or ""),
+ debug_run_info_len=len(debug_run_info_text),
+ workflow_knowledge_base_len=len(workflow_knowledge_base),
+ llm_response_len=len(llm_response),
+ llm_response=llm_response,
+ )
if isinstance(llm_response, dict) and "output" in llm_response:
action_data = llm_response["output"]