diff --git a/apps/rowboat/app/actions.ts b/apps/rowboat/app/actions.ts index a785b261..c42c15a3 100644 --- a/apps/rowboat/app/actions.ts +++ b/apps/rowboat/app/actions.ts @@ -1,7 +1,7 @@ 'use server'; import { redirect } from "next/navigation"; -import { SimulationData, EmbeddingDoc, GetInformationToolResult, DataSource, PlaygroundChat, AgenticAPIChatRequest, AgenticAPIChatResponse, convertFromAgenticAPIChatMessages, WebpageCrawlResponse, Workflow, WorkflowAgent, CopilotAPIRequest, CopilotAPIResponse, CopilotMessage, CopilotWorkflow, convertToCopilotWorkflow, convertToCopilotApiMessage, convertToCopilotMessage, CopilotAssistantMessage, CopilotChatContext, convertToCopilotApiChatContext, Scenario, ClientToolCallRequestBody, ClientToolCallJwt, ClientToolCallRequest, WithStringId, Project } from "./lib/types"; +import { SimulationData, EmbeddingDoc, GetInformationToolResult, DataSource, PlaygroundChat, AgenticAPIChatRequest, AgenticAPIChatResponse, convertFromAgenticAPIChatMessages, WebpageCrawlResponse, Workflow, WorkflowAgent, CopilotAPIRequest, CopilotAPIResponse, CopilotMessage, CopilotWorkflow, convertToCopilotWorkflow, convertToCopilotApiMessage, convertToCopilotMessage, CopilotAssistantMessage, CopilotChatContext, convertToCopilotApiChatContext, Scenario, ClientToolCallRequestBody, ClientToolCallJwt, ClientToolCallRequest, WithStringId, Project, WorkflowTool, WorkflowPrompt } from "./lib/types"; import { ObjectId, WithId } from "mongodb"; import { generateObject, generateText, tool, embed } from "ai"; import { dataSourcesCollection, embeddingsCollection, projectsCollection, webpagesCollection, agentWorkflowsCollection, scenariosCollection, projectMembersCollection } from "@/app/lib/mongodb"; @@ -16,6 +16,7 @@ import { SignJWT } from "jose"; import { Claims, getSession } from "@auth0/nextjs-auth0"; import { revalidatePath } from "next/cache"; import { baseWorkflow, callClientToolWebhook, getAgenticApiResponse } from "./lib/utils"; +import { assert, error } from "node:console"; const crawler = new FirecrawlApp({ apiKey: process.env.FIRECRAWL_API_KEY || '' }); @@ -522,6 +523,67 @@ export async function getCopilotResponse( content: json.response.replace(/^```json\n/, '').replace(/\n```$/, ''), }); + // assert that msg.content is a CopilotAssistantMessage + assert(msg.role === 'assistant'); + if (msg.role === 'assistant') { + for (const part of msg.content.response) { + if (part.type === 'action') { + switch (part.content.config_type) { + case 'tool': { + const test = { + name: 'test', + description: 'test', + ...part.content.config_changes, + } as z.infer; + const result = WorkflowTool.safeParse(test); + if (!result.success) { + part.content.error = result.error.message; + } + break; + } + case 'agent': { + const test = { + name: 'test', + description: 'test', + type: 'conversation', + instructions: 'test', + prompts: [], + tools: [], + model: 'gpt-4o', + ragReturnType: 'chunks', + ragK: 10, + connectedAgents: [], + controlType: 'retain', + ...part.content.config_changes, + } as z.infer; + const result = WorkflowAgent.safeParse(test); + if (!result.success) { + part.content.error = result.error.message; + } + break; + } + case 'prompt': { + const test = { + name: 'test', + type: 'base_prompt', + prompt: "test", + ...part.content.config_changes, + } as z.infer; + const result = WorkflowPrompt.safeParse(test); + if (!result.success) { + part.content.error = result.error.message; + } + break; + } + default: { + part.content.error = `Unknown config type: ${part.content.config_type}`; + break; + } + } + } + } + } + return { message: msg as z.infer, rawRequest: request, diff --git a/apps/rowboat/app/lib/types.ts b/apps/rowboat/app/lib/types.ts index f7f11043..6d00e283 100644 --- a/apps/rowboat/app/lib/types.ts +++ b/apps/rowboat/app/lib/types.ts @@ -270,6 +270,7 @@ export const CopilotAssistantMessageActionPart = z.object({ name: z.string(), change_description: z.string(), config_changes: z.record(z.string(), z.unknown()), + error: z.string().optional(), }) }); diff --git a/apps/rowboat/app/projects/[projectId]/workflow/copilot_actions.tsx b/apps/rowboat/app/projects/[projectId]/workflow/copilot_actions.tsx index f52a1894..5a603aaa 100644 --- a/apps/rowboat/app/projects/[projectId]/workflow/copilot_actions.tsx +++ b/apps/rowboat/app/projects/[projectId]/workflow/copilot_actions.tsx @@ -5,7 +5,8 @@ import { z } from "zod"; import { Workflow, CopilotAssistantMessage, CopilotAssistantMessageActionPart } from "@/app/lib/types"; import { PreviewModalProvider, usePreviewModal } from './preview-modal'; import { getAppliedChangeKey } from "./copilot"; -import { CheckCheckIcon, CheckIcon, ChevronsDownIcon, ChevronsUpIcon, EyeIcon, PencilIcon, PlusIcon } from "lucide-react"; +import { AlertTriangleIcon, CheckCheckIcon, CheckIcon, ChevronsDownIcon, ChevronsUpIcon, EyeIcon, PencilIcon, PlusIcon } from "lucide-react"; +import { Tooltip } from "@nextui-org/react"; const ActionContext = createContext<{ msgIndex: number; @@ -51,12 +52,16 @@ export function Action({ return
{expanded && + {action.error &&
+
This configuration is invalid and cannot be applied:
+
{action.error}
+
}
{Object.entries(action.config_changes).map(([key, value]) => { return @@ -64,8 +69,14 @@ export function Action({
}
-
} + {!action.error &&
- + } - {action.action === 'edit' &&