diff --git a/apps/rowboat/app/actions/mcp_actions.ts b/apps/rowboat/app/actions/mcp_actions.ts new file mode 100644 index 00000000..1062a372 --- /dev/null +++ b/apps/rowboat/app/actions/mcp_actions.ts @@ -0,0 +1,82 @@ +"use server"; +import { z } from "zod"; +import { WorkflowTool } from "../lib/types/workflow_types"; +import { Client } from "@modelcontextprotocol/sdk/client/index.js"; +import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js"; +import { projectAuthCheck } from "./project_actions"; +import { callMcpTool } from "../lib/utils"; +import { projectsCollection } from "../lib/mongodb"; +import { Project } from "../lib/types/project_types"; + +export async function fetchMcpTools(projectId: string): Promise[]> { + await projectAuthCheck(projectId); + + const project = await projectsCollection.findOne({ + _id: projectId, + }); + + const mcpServers = project?.mcpServers ?? []; + + const tools: z.infer[] = []; + + for (const mcpServer of mcpServers) { + try { + const transport = new SSEClientTransport(new URL(mcpServer.url)); + + const client = new Client( + { + name: "rowboat-client", + version: "1.0.0" + }, + { + capabilities: { + prompts: {}, + resources: {}, + tools: {} + } + } + ); + + await client.connect(transport); + + // List tools + const result = await client.listTools(); + + await client.close(); + + tools.push(...result.tools.map((mcpTool) => { + let props = mcpTool.inputSchema.properties as Record; + const tool: z.infer = { + name: mcpTool.name, + description: mcpTool.description ?? "", + parameters: { + type: "object", + properties: props ?? {}, + required: mcpTool.inputSchema.required as string[] ?? [], + }, + isMcp: true, + mcpServerName: mcpServer.name, + } + return tool; + })); + } catch (e) { + console.error(`Error fetching MCP tools from ${mcpServer.name}: ${e}`); + } + } + + return tools; +} + +export async function updateMcpServers(projectId: string, mcpServers: z.infer['mcpServers']): Promise { + await projectAuthCheck(projectId); + await projectsCollection.updateOne({ + _id: projectId, + }, { $set: { mcpServers } }); +} + +export async function executeMcpTool(projectId: string, mcpServerName: string, toolName: string, parameters: Record): Promise { + await projectAuthCheck(projectId); + + const result = await callMcpTool(projectId, mcpServerName, toolName, parameters); + return result; +} \ No newline at end of file diff --git a/apps/rowboat/app/api/v1/[projectId]/chat/route.ts b/apps/rowboat/app/api/v1/[projectId]/chat/route.ts index f4d9c4fc..30be58af 100644 --- a/apps/rowboat/app/api/v1/[projectId]/chat/route.ts +++ b/apps/rowboat/app/api/v1/[projectId]/chat/route.ts @@ -5,7 +5,7 @@ import { ObjectId } from "mongodb"; import { authCheck } from "../../utils"; import { ApiRequest, ApiResponse } from "../../../../lib/types/types"; import { AgenticAPIChatRequest, AgenticAPIChatMessage, convertFromAgenticApiToApiMessages, convertFromApiToAgenticApiMessages, convertWorkflowToAgenticAPI } from "../../../../lib/types/agents_api_types"; -import { getAgenticApiResponse, callClientToolWebhook, runRAGToolCall, mockToolResponse } from "../../../../lib/utils"; +import { getAgenticApiResponse, callClientToolWebhook, runRAGToolCall, mockToolResponse, callMcpTool } from "../../../../lib/utils"; import { check_query_limit } from "../../../../lib/rate_limiting"; import { apiV1 } from "rowboat-shared"; import { PrefixLogger } from "../../../../lib/utils"; @@ -162,7 +162,7 @@ export async function POST( return Response.json({ error: "Error running RAG tool call" }, { status: 500 }); } } else { - logger.log(`Running client tool webhook for tool ${toolCall.function.name}`); + logger.log(`Processing tool call ${toolCall.function.name}`); try { // if tool is supposed to be mocked, mock it @@ -170,6 +170,10 @@ export async function POST( if (testProfile?.mockTools || workflowTool?.mockTool) { logger.log(`Mocking tool call ${toolCall.function.name}`); result = await mockToolResponse(toolCall.id, currentMessages, testProfile?.mockPrompt || workflowTool?.mockInstructions || ''); + } else if (workflowTool?.isMcp) { + // else run the tool call by calling the MCP tool + logger.log(`Calling MCP tool: ${toolCall.function.name}`); + result = await callMcpTool(projectId, workflowTool.mcpServerName ?? 'default', toolCall.function.name, JSON.parse(toolCall.function.arguments)); } else { // else run the tool call by calling the client tool webhook logger.log(`Running client tool webhook for tool ${toolCall.function.name}`); diff --git a/apps/rowboat/app/api/widget/v1/chats/[chatId]/turn/route.ts b/apps/rowboat/app/api/widget/v1/chats/[chatId]/turn/route.ts index 19a19edc..ccb4f3ea 100644 --- a/apps/rowboat/app/api/widget/v1/chats/[chatId]/turn/route.ts +++ b/apps/rowboat/app/api/widget/v1/chats/[chatId]/turn/route.ts @@ -8,7 +8,7 @@ import { convertFromAgenticAPIChatMessages } from "../../../../../../lib/types/a import { convertToAgenticAPIChatMessages } from "../../../../../../lib/types/agents_api_types"; import { convertWorkflowToAgenticAPI } from "../../../../../../lib/types/agents_api_types"; import { AgenticAPIChatRequest } from "../../../../../../lib/types/agents_api_types"; -import { callClientToolWebhook, getAgenticApiResponse, runRAGToolCall, mockToolResponse } from "../../../../../../lib/utils"; +import { callClientToolWebhook, getAgenticApiResponse, runRAGToolCall, mockToolResponse, callMcpTool } from "../../../../../../lib/utils"; import { check_query_limit } from "../../../../../../lib/rate_limiting"; import { PrefixLogger } from "../../../../../../lib/utils"; @@ -158,14 +158,22 @@ export async function POST( [...messages, ...unsavedMessages], workflowTool.mockInstructions || '' ); + } else if (workflowTool?.isMcp) { + logger.log(`Calling MCP tool: ${toolCall.function.name}`); + return await callMcpTool( + session.projectId, + workflowTool.mcpServerName ?? 'default', + toolCall.function.name, + JSON.parse(toolCall.function.arguments) + ); + } else { + logger.log(`Calling webhook for tool: ${toolCall.function.name}`); + return await callClientToolWebhook( + toolCall, + [...messages, ...unsavedMessages], + session.projectId, + ); } - - logger.log(`Calling webhook for tool: ${toolCall.function.name}`); - return await callClientToolWebhook( - toolCall, - [...messages, ...unsavedMessages], - session.projectId, - ); } catch (error) { logger.log(`Error executing tool call ${toolCall.id}: ${error}`); return { error: "Tool execution failed" }; diff --git a/apps/rowboat/app/lib/components/structured-list.tsx b/apps/rowboat/app/lib/components/structured-list.tsx index adb4b962..f957c98f 100644 --- a/apps/rowboat/app/lib/components/structured-list.tsx +++ b/apps/rowboat/app/lib/components/structured-list.tsx @@ -23,7 +23,8 @@ export function ListItem({ onClick, disabled, rightElement, - selectedRef + selectedRef, + icon }: { name: string; isSelected: boolean; @@ -31,6 +32,7 @@ export function ListItem({ disabled?: boolean; rightElement?: React.ReactNode; selectedRef?: React.RefObject; + icon?: React.ReactNode; }) { return ( ); diff --git a/apps/rowboat/app/lib/types/project_types.ts b/apps/rowboat/app/lib/types/project_types.ts index 50df41b4..54192314 100644 --- a/apps/rowboat/app/lib/types/project_types.ts +++ b/apps/rowboat/app/lib/types/project_types.ts @@ -1,4 +1,5 @@ import { z } from "zod"; + export const Project = z.object({ _id: z.string().uuid(), name: z.string(), @@ -11,16 +12,22 @@ export const Project = z.object({ publishedWorkflowId: z.string().optional(), nextWorkflowNumber: z.number().optional(), testRunCounter: z.number().default(0), -});export const ProjectMember = z.object({ + mcpServers: z.array(z.object({ + name: z.string(), + url: z.string(), + })).optional(), +}); + +export const ProjectMember = z.object({ userId: z.string(), projectId: z.string(), createdAt: z.string().datetime(), lastUpdatedAt: z.string().datetime(), }); + export const ApiKey = z.object({ projectId: z.string(), key: z.string(), createdAt: z.string().datetime(), lastUsedAt: z.string().datetime().optional(), -}); - +}); \ No newline at end of file diff --git a/apps/rowboat/app/lib/types/workflow_types.ts b/apps/rowboat/app/lib/types/workflow_types.ts index 5d9599d8..307563c5 100644 --- a/apps/rowboat/app/lib/types/workflow_types.ts +++ b/apps/rowboat/app/lib/types/workflow_types.ts @@ -45,6 +45,8 @@ export const WorkflowTool = z.object({ })), required: z.array(z.string()).optional(), }), + isMcp: z.boolean().default(false).optional(), + mcpServerName: z.string().optional(), }); export const Workflow = z.object({ name: z.string().optional(), diff --git a/apps/rowboat/app/lib/utils.ts b/apps/rowboat/app/lib/utils.ts index d72088c2..2e395ca3 100644 --- a/apps/rowboat/app/lib/utils.ts +++ b/apps/rowboat/app/lib/utils.ts @@ -18,7 +18,54 @@ import { qdrantClient } from "./qdrant"; import { EmbeddingRecord } from "./types/datasource_types"; import { ApiMessage } from "./types/types"; import { openai } from "@ai-sdk/openai"; -import { TestProfile } from "./types/testing_types"; +import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js"; +import { Client } from "@modelcontextprotocol/sdk/client/index.js"; + +export async function callMcpTool( + projectId: string, + mcpServerName: string, + toolName: string, + parameters: Record, +): Promise { + const project = await projectsCollection.findOne({ + "_id": projectId, + }); + if (!project) { + throw new Error('Project not found'); + } + + const mcpServer = project.mcpServers?.find(s => s.name === mcpServerName); + if (!mcpServer) { + throw new Error('MCP server not found'); + } + + const transport = new SSEClientTransport(new URL(mcpServer.url)); + + const client = new Client( + { + name: "rowboat-client", + version: "1.0.0" + }, + { + capabilities: { + prompts: {}, + resources: {}, + tools: {} + } + } + ); + + await client.connect(transport); + + const result = await client.callTool({ + name: toolName, + arguments: parameters, + }); + + await client.close(); + + return result; +} export async function callClientToolWebhook( toolCall: z.infer['tool_calls'][number], diff --git a/apps/rowboat/app/projects/[projectId]/config/app.tsx b/apps/rowboat/app/projects/[projectId]/config/app.tsx index cb4944c6..0716d32b 100644 --- a/apps/rowboat/app/projects/[projectId]/config/app.tsx +++ b/apps/rowboat/app/projects/[projectId]/config/app.tsx @@ -2,8 +2,9 @@ import { Metadata } from "next"; import { Spinner, Textarea, Button, Dropdown, DropdownMenu, DropdownItem, DropdownTrigger, Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Input, useDisclosure, Divider } from "@heroui/react"; -import { ReactNode, useEffect, useState, useCallback } from "react"; +import { ReactNode, useEffect, useState, useCallback, useMemo } from "react"; import { getProjectConfig, updateProjectName, updateWebhookUrl, createApiKey, deleteApiKey, listApiKeys, deleteProject, rotateSecret } from "../../../actions/project_actions"; +import { updateMcpServers } from "../../../actions/mcp_actions"; import { CopyButton } from "../../../lib/components/copy-button"; import { EditableField } from "../../../lib/components/editable-field"; import { EyeIcon, EyeOffIcon, CopyIcon, MoreVerticalIcon, PlusIcon, EllipsisVerticalIcon } from "lucide-react"; @@ -113,6 +114,227 @@ export function BasicSettingsSection({ ; } +function McpServersSection({ + projectId, +}: { + projectId: string; +}) { + const [servers, setServers] = useState>([]); + const [originalServers, setOriginalServers] = useState>([]); + const [loading, setLoading] = useState(true); + const [saving, setSaving] = useState(false); + const [message, setMessage] = useState<{ type: 'success' | 'error', text: string } | null>(null); + const { isOpen, onOpen, onClose } = useDisclosure(); + const [newServer, setNewServer] = useState({ name: '', url: '' }); + const [validationErrors, setValidationErrors] = useState<{ + name?: string; + url?: string; + }>({}); + + // Load initial servers + useEffect(() => { + setLoading(true); + getProjectConfig(projectId).then((project) => { + const initialServers = project.mcpServers || []; + setServers(JSON.parse(JSON.stringify(initialServers))); // Deep copy + setOriginalServers(JSON.parse(JSON.stringify(initialServers))); // Deep copy + setLoading(false); + }); + }, [projectId]); + + // Check if there are unsaved changes by comparing the arrays + const hasChanges = useMemo(() => { + if (servers.length !== originalServers.length) return true; + return servers.some((server, index) => { + return server.name !== originalServers[index]?.name || + server.url !== originalServers[index]?.url; + }); + }, [servers, originalServers]); + + const handleAddServer = () => { + setNewServer({ name: '', url: '' }); + setValidationErrors({}); + onOpen(); + }; + + const handleRemoveServer = (index: number) => { + setServers(servers.filter((_, i) => i !== index)); + }; + + const handleCreateServer = () => { + // Clear previous validation errors + setValidationErrors({}); + + const errors: typeof validationErrors = {}; + + // Validate name uniqueness + if (!newServer.name.trim()) { + errors.name = 'Server name is required'; + } else if (servers.some(s => s.name === newServer.name)) { + errors.name = 'Server name must be unique'; + } + + // Validate URL + if (!newServer.url.trim()) { + errors.url = 'Server URL is required'; + } else { + try { + new URL(newServer.url); + } catch { + errors.url = 'Invalid URL format'; + } + } + + if (Object.keys(errors).length > 0) { + setValidationErrors(errors); + return; + } + + setServers([...servers, newServer]); + onClose(); + }; + + const handleSave = async () => { + setSaving(true); + try { + await updateMcpServers(projectId, servers); + setOriginalServers(JSON.parse(JSON.stringify(servers))); // Update original servers after successful save + setMessage({ type: 'success', text: 'Servers updated successfully' }); + setTimeout(() => setMessage(null), 3000); + } catch (error) { + setMessage({ type: 'error', text: 'Failed to update servers' }); + } + setSaving(false); + }; + + return
+
+
+

+ MCP servers are used to execute MCP tools. +

+ +
+ + {loading ? ( + + ) : ( + <> +
+ {servers.map((server, index) => ( +
+
+
{server.name}
+
{server.url}
+
+ +
+ ))} + {servers.length === 0 && ( +
+ No servers configured +
+ )} +
+ + {hasChanges && ( +
+ +
+ )} + + {message && ( +
+ {message.text} +
+ )} + + )} + + + + Add MCP Server + +
+ { + setNewServer({ ...newServer, name: e.target.value }); + // Clear name error when user types + if (validationErrors.name) { + setValidationErrors(prev => ({ + ...prev, + name: undefined + })); + } + }} + errorMessage={validationErrors.name} + isInvalid={!!validationErrors.name} + isRequired + /> + { + setNewServer({ ...newServer, url: e.target.value }); + // Clear URL error when user types + if (validationErrors.url) { + setValidationErrors(prev => ({ + ...prev, + url: undefined + })); + } + }} + errorMessage={validationErrors.url} + isInvalid={!!validationErrors.url} + isRequired + /> +
+
+ + + + +
+
+
+
; +} + function ApiKeyDisplay({ apiKey }: { apiKey: string }) { const [isVisible, setIsVisible] = useState(false); @@ -587,6 +809,7 @@ export default function App({ + {useChatWidget && } diff --git a/apps/rowboat/app/projects/[projectId]/playground/messages.tsx b/apps/rowboat/app/projects/[projectId]/playground/messages.tsx index dd8d667a..8c42b527 100644 --- a/apps/rowboat/app/projects/[projectId]/playground/messages.tsx +++ b/apps/rowboat/app/projects/[projectId]/playground/messages.tsx @@ -4,15 +4,14 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import z from "zod"; import { Workflow } from "../../../lib/types/workflow_types"; import { WorkflowTool } from "../../../lib/types/workflow_types"; -import { WebpageCrawlResponse } from "../../../lib/types/tool_types"; import { GetInformationToolResult } from "../../../lib/types/tool_types"; -import { executeClientTool, getInformationTool, scrapeWebpage, suggestToolResponse } from "../../../actions/actions"; +import { executeClientTool, getInformationTool, suggestToolResponse } from "../../../actions/actions"; import MarkdownContent from "../../../lib/components/markdown-content"; -import Link from "next/link"; import { apiV1 } from "rowboat-shared"; import { EditableField } from "../../../lib/components/editable-field"; -import { MessageSquareIcon, EllipsisIcon, CircleCheckIcon, ChevronsDownIcon, ChevronsRightIcon, ChevronRightIcon, ChevronDownIcon, ExternalLinkIcon, XIcon } from "lucide-react"; +import { MessageSquareIcon, EllipsisIcon, CircleCheckIcon, ChevronRightIcon, ChevronDownIcon, XIcon } from "lucide-react"; import { TestProfile } from "@/app/lib/types/testing_types"; +import { executeMcpTool } from "@/app/actions/mcp_actions"; function UserMessage({ content }: { content: string }) { return
@@ -201,6 +200,17 @@ function ToolCall({ systemMessage={systemMessage} />; } + if (matchingWorkflowTool?.isMcp) { + return ; + } return ; } +function McpToolCall({ + toolCall, + result: availableResult, + handleResult, + projectId, + messages, + sender, + workflowTool, +}: { + toolCall: z.infer['tool_calls'][number]; + result: z.infer | undefined; + handleResult: (result: z.infer) => void; + projectId: string; + messages: z.infer[]; + sender: string | null | undefined; + workflowTool: z.infer; +}) { + const [result, setResult] = useState | undefined>(availableResult); + + useEffect(() => { + if (result) { + return; + } + let ignore = false; + + async function process() { + let response; + try { + response = await executeMcpTool( + projectId, + workflowTool.mcpServerName || '', + workflowTool.name, + JSON.parse(toolCall.function.arguments), + ); + } catch (e) { + response = { + error: (e as Error).message, + }; + } + if (ignore) { + return; + } + + const result: z.infer = { + role: 'tool', + tool_call_id: toolCall.id, + tool_name: toolCall.function.name, + content: JSON.stringify(response), + }; + setResult(result); + handleResult(result); + } + process(); + + return () => { + ignore = true; + }; + }, [result, toolCall, projectId, messages, handleResult, workflowTool.mcpServerName, workflowTool.name]); + + return
+ {sender &&
{sender}
} +
+ + +
+ + {result && } +
+
+
; +} + function ClientToolCall({ toolCall, result: availableResult, @@ -407,8 +489,8 @@ function ClientToolCall({
- - {result && } + + {result && }
; diff --git a/apps/rowboat/app/projects/[projectId]/workflow/entity_list.tsx b/apps/rowboat/app/projects/[projectId]/workflow/entity_list.tsx index 0a243951..278a4bc3 100644 --- a/apps/rowboat/app/projects/[projectId]/workflow/entity_list.tsx +++ b/apps/rowboat/app/projects/[projectId]/workflow/entity_list.tsx @@ -6,7 +6,7 @@ import { Dropdown, DropdownItem, DropdownTrigger, DropdownMenu } from "@heroui/r import { useRef, useEffect } from "react"; import { ActionButton, StructuredPanel } from "../../../lib/components/structured-panel"; import clsx from "clsx"; -import { EllipsisVerticalIcon } from "lucide-react"; +import { EllipsisVerticalIcon, ImportIcon } from "lucide-react"; import { SectionHeader, ListItem } from "../../../lib/components/structured-list"; interface EntityListProps { @@ -100,6 +100,7 @@ export function EntityList({ onClick={() => onSelectTool(tool.name)} selectedRef={selectedEntity?.type === "tool" && selectedEntity.name === tool.name ? selectedRef : undefined} rightElement={} + icon={tool.isMcp ? : <>} /> ))} diff --git a/apps/rowboat/app/projects/[projectId]/workflow/mcp_imports.tsx b/apps/rowboat/app/projects/[projectId]/workflow/mcp_imports.tsx new file mode 100644 index 00000000..c6700480 --- /dev/null +++ b/apps/rowboat/app/projects/[projectId]/workflow/mcp_imports.tsx @@ -0,0 +1,151 @@ +"use client"; +import { useCallback, useEffect, useState } from "react"; +import { Button, Spinner, Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Checkbox } from "@heroui/react"; +import { z } from "zod"; +import { WorkflowTool } from "@/app/lib/types/workflow_types"; +import { RefreshCwIcon } from "lucide-react"; +import { fetchMcpTools } from "@/app/actions/mcp_actions"; + +interface McpImportToolsProps { + projectId: string; + isOpen: boolean; + onOpenChange: (open: boolean) => void; + onImport: (tools: z.infer[]) => void; +} + +export function McpImportTools({ projectId, isOpen, onOpenChange, onImport }: McpImportToolsProps) { + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + const [tools, setTools] = useState[]>([]); + const [selectedTools, setSelectedTools] = useState>(new Set()); + + const process = useCallback(async () => { + setLoading(true); + setError(null); + setSelectedTools(new Set()); + try { + const result = await fetchMcpTools(projectId); + setTools(result); + // Select all tools by default + setSelectedTools(new Set(result.map((_, index) => index))); + } catch (error) { + setError(`Unable to fetch tools: ${error}`); + } finally { + setLoading(false); + } + }, [projectId]); + + useEffect(() => { + console.log("mcp import tools useEffect", isOpen); + if (isOpen) { + process(); + } + }, [isOpen, process]); + + return ( + + + {(onClose) => ( + <> + Import from MCP servers + + {loading &&
+ + Fetching tools... +
} + {error &&
+ {error} + +
} + {!loading && !error && <> +
+
+ {tools.length === 0 ? "No tools found" : `Found ${tools.length} tools:`} +
+ +
+ {tools.length > 0 &&
+
+
+ 0 && selectedTools.size < tools.length} + onValueChange={(checked) => { + if (checked) { + setSelectedTools(new Set(tools.map((_, i) => i))); + } else { + setSelectedTools(new Set()); + } + }} + /> +
+
Server
+
Tool Name
+
+
+ {tools.map((t, index) => ( +
+
+ { + const newSelected = new Set(selectedTools); + if (checked) { + newSelected.add(index); + } else { + newSelected.delete(index); + } + setSelectedTools(newSelected); + }} + /> +
+
+
+ {t.mcpServerName} +
+
+
{t.name}
+
+ ))} +
+
} + {tools.length > 0 && ( +
+ {selectedTools.size} of {tools.length} tools selected +
+ )} + } +
+ + + {tools.length > 0 && } + + + )} +
+
+ ); +} \ No newline at end of file diff --git a/apps/rowboat/app/projects/[projectId]/workflow/tool_config.tsx b/apps/rowboat/app/projects/[projectId]/workflow/tool_config.tsx index 6ca48784..181d1525 100644 --- a/apps/rowboat/app/projects/[projectId]/workflow/tool_config.tsx +++ b/apps/rowboat/app/projects/[projectId]/workflow/tool_config.tsx @@ -6,16 +6,15 @@ import { ActionButton, StructuredPanel } from "../../../lib/components/structure import { EditableField } from "../../../lib/components/editable-field"; import { Divider } from "@heroui/react"; import { Label } from "../../../lib/components/label"; -import { TrashIcon, XIcon } from "lucide-react"; +import { ImportIcon, XIcon } from "lucide-react"; import { useState } from "react"; -import { Link as NextUILink } from "@heroui/react"; -import Link from "next/link"; export function ParameterConfig({ param, handleUpdate, handleDelete, - handleRename + handleRename, + readOnly }: { param: { name: string, @@ -29,11 +28,12 @@ export function ParameterConfig({ required: boolean }) => void, handleDelete: (name: string) => void, - handleRename: (oldName: string, newName: string) => void + handleRename: (oldName: string, newName: string) => void, + readOnly?: boolean }) { return handleDelete(param.name)} @@ -41,7 +41,7 @@ export function ParameterConfig({ > Remove - ]} + ] : []} >
@@ -69,6 +70,7 @@ export function ParameterConfig({ type: Array.from(keys)[0] as string }); }} + isDisabled={readOnly} > {['string', 'number', 'boolean', 'array', 'object'].map(type => ( @@ -89,6 +91,7 @@ export function ParameterConfig({ description: desc }); }} + locked={readOnly} /> @@ -102,6 +105,7 @@ export function ParameterConfig({ required: !param.required }); }} + isDisabled={readOnly} > Required @@ -121,6 +125,7 @@ export function ToolConfig({ handleClose: () => void }) { const [selectedParams, setSelectedParams] = useState(new Set([])); + const isReadOnly = tool.isMcp; function handleParamRename(oldName: string, newName: string) { const newProperties = { ...tool.parameters!.properties }; @@ -193,6 +198,13 @@ export function ToolConfig({ ]}>
+ {tool.isMcp &&
+
+ +
Imported from MCP server: {tool.mcpServerName}
+
+
} + @@ -221,89 +234,92 @@ export function ToolConfig({ description: value })} placeholder="Describe what this tool does..." + locked={isReadOnly} /> -
+ + + }
- + }
); diff --git a/apps/rowboat/app/projects/[projectId]/workflow/workflow_editor.tsx b/apps/rowboat/app/projects/[projectId]/workflow/workflow_editor.tsx index 4923e067..b3eaa203 100644 --- a/apps/rowboat/app/projects/[projectId]/workflow/workflow_editor.tsx +++ b/apps/rowboat/app/projects/[projectId]/workflow/workflow_editor.tsx @@ -26,10 +26,10 @@ import { apiV1 } from "rowboat-shared"; import { publishWorkflow, renameWorkflow, saveWorkflow } from "../../../actions/workflow_actions"; import { PublishedBadge } from "./published_badge"; import { BackIcon, HamburgerIcon, WorkflowIcon } from "../../../lib/components/icons"; -import { CopyIcon, Layers2Icon, RadioIcon, RedoIcon, Sparkles, UndoIcon } from "lucide-react"; +import { CopyIcon, ImportIcon, Layers2Icon, RadioIcon, RedoIcon, ServerIcon, Sparkles, UndoIcon } from "lucide-react"; import { EntityList } from "./entity_list"; import { CopilotMessage } from "../../../lib/types/copilot_types"; -import { TestProfile } from "@/app/lib/types/testing_types"; +import { McpImportTools } from "./mcp_imports"; enablePatches(); @@ -132,6 +132,9 @@ export type Action = { } | { type: "restore_state"; state: StateItem; +} | { + type: "import_mcp_tools"; + tools: z.infer[]; }; function reducer(state: State, action: Action): State { @@ -509,6 +512,26 @@ function reducer(state: State, action: Action): State { draft.workflow.startAgent = action.name; draft.chatKey++; break; + case "import_mcp_tools": + if (isLive) { + break; + } + // Process each tool one by one + action.tools.forEach(newTool => { + const existingToolIndex = draft.workflow.tools.findIndex( + tool => tool.name === newTool.name + ); + + if (existingToolIndex !== -1) { + // Replace existing tool + draft.workflow.tools[existingToolIndex] = newTool; + } else { + // Add new tool + draft.workflow.tools.push(newTool); + } + }); + draft.chatKey++; + break; } } ); @@ -575,6 +598,7 @@ export function WorkflowEditor({ const [loadingResponse, setLoadingResponse] = useState(false); const [loadingMessage, setLoadingMessage] = useState("Thinking..."); const [responseError, setResponseError] = useState(null); + const [isMcpImportModalOpen, setIsMcpImportModalOpen] = useState(false); console.log(`workflow editor chat key: ${state.present.chatKey}`); @@ -697,6 +721,10 @@ export function WorkflowEditor({ } }, [isLive]); + function handleImportMcpTools(tools: z.infer[]) { + dispatch({ type: "import_mcp_tools", tools }); + } + useEffect(() => { if (state.present.pendingChanges && state.present.workflow) { saveQueue.current.push(state.present.workflow); @@ -732,7 +760,7 @@ export function WorkflowEditor({ { if (key === 'switch') { @@ -747,6 +775,9 @@ export function WorkflowEditor({ if (key === 'clipboard') { handleCopyJSON(); } + if (key === 'mcp') { + setIsMcpImportModalOpen(true); + } }} > Copy as JSON + } + > + MCP: Import tools + @@ -935,5 +972,11 @@ export function WorkflowEditor({ } + ; } diff --git a/apps/rowboat/package-lock.json b/apps/rowboat/package-lock.json index ad30d0bd..8b8583f3 100644 --- a/apps/rowboat/package-lock.json +++ b/apps/rowboat/package-lock.json @@ -20,6 +20,7 @@ "@langchain/core": "^0.3.7", "@langchain/textsplitters": "^0.1.0", "@mendable/firecrawl-js": "^1.0.3", + "@modelcontextprotocol/sdk": "^1.7.0", "@primer/react": "^36.27.0", "@qdrant/js-client-rest": "^1.13.0", "ai": "^3.3.28", @@ -10270,6 +10271,25 @@ "zod-to-json-schema": "^3.23.0" } }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.7.0.tgz", + "integrity": "sha512-IYPe/FLpvF3IZrd/f5p5ffmWhMc3aEMuM2wGJASDqC2Ge7qatVCdbfPx3n/5xFeb19xN0j/911M2AaFuircsWA==", + "dependencies": { + "content-type": "^1.0.5", + "cors": "^2.8.5", + "eventsource": "^3.0.2", + "express": "^5.0.1", + "express-rate-limit": "^7.5.0", + "pkce-challenge": "^4.1.0", + "raw-body": "^3.0.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.24.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@mongodb-js/saslprep": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.8.tgz", @@ -13920,6 +13940,37 @@ "node": ">=6.5" } }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-db": { + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz", + "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-types": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.0.tgz", + "integrity": "sha512-XqoSHeCGjVClAmoGFG3lVFqQFRIrTVw2OH3axRqAcfaw+gHWIfnASS92AV+Rl/mk0MupgZTRHQOjxY6YVnzK5w==", + "dependencies": { + "mime-db": "^1.53.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", @@ -14438,6 +14489,50 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/body-parser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.1.0.tgz", + "integrity": "sha512-/hPxh61E+ll0Ujp24Ilm64cykicul1ypfwjVttduAiEdtnJFvLePSrIPk+HMImtNv5270wOGCb1Tns2rybMkoQ==", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.5.2", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", + "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -14520,6 +14615,14 @@ "node": ">=10.16.0" } }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/call-bind": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", @@ -14539,6 +14642,33 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -14848,6 +14978,25 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -14862,6 +15011,26 @@ "node": ">= 0.6" } }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/cosmiconfig": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", @@ -15029,11 +15198,11 @@ } }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -15044,6 +15213,11 @@ } } }, + "node_modules/debug/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "node_modules/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -15152,6 +15326,14 @@ "node": ">=0.4.0" } }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -15160,6 +15342,15 @@ "node": ">=6" } }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, "node_modules/detect-libc": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", @@ -15289,11 +15480,29 @@ "url": "https://dotenvx.com" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, "node_modules/electron-to-chromium": { "version": "1.5.74", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.74.tgz", @@ -15305,6 +15514,14 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/encoding-sniffer": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.0.tgz", @@ -15415,13 +15632,9 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "engines": { "node": ">= 0.4" } @@ -15430,7 +15643,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, "engines": { "node": ">= 0.4" } @@ -15481,10 +15693,9 @@ } }, "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", - "dev": true, + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "dependencies": { "es-errors": "^1.3.0" }, @@ -15580,6 +15791,11 @@ "node": ">=6" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -16022,6 +16238,14 @@ "node": ">=0.10.0" } }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", @@ -16035,6 +16259,17 @@ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" }, + "node_modules/eventsource": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.5.tgz", + "integrity": "sha512-LT/5J605bx5SNyE+ITBDiM3FxffBiq9un7Vx0EwMDM3vg8sWKx/tO2zC+LMqZ+smAM0F2hblaDZUVZF0te2pSw==", + "dependencies": { + "eventsource-parser": "^3.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/eventsource-parser": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-1.1.2.tgz", @@ -16043,6 +16278,113 @@ "node": ">=14.18" } }, + "node_modules/eventsource/node_modules/eventsource-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.0.tgz", + "integrity": "sha512-T1C0XCUimhxVQzW4zFipdx0SficT651NnkR0ZSH3yQwh+mFMdLfgjABVi4YtMTtaL4s168593DaoaRLMqryavA==", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/express": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.0.1.tgz", + "integrity": "sha512-ORF7g6qGnD+YtUG9yx4DFoqCShNMmUKiXuT5oWMHiOvt/4WFbHC6yCwQMTSBMno7AqntNCAzzcnnjowRkTL9eQ==", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.0.1", + "content-disposition": "^1.0.0", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "^1.2.1", + "debug": "4.3.6", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "^2.0.0", + "fresh": "2.0.0", + "http-errors": "2.0.0", + "merge-descriptors": "^2.0.0", + "methods": "~1.1.2", + "mime-types": "^3.0.0", + "on-finished": "2.4.1", + "once": "1.4.0", + "parseurl": "~1.3.3", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "router": "^2.0.0", + "safe-buffer": "5.2.1", + "send": "^1.1.0", + "serve-static": "^2.1.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "^2.0.0", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/express-rate-limit": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz", + "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": "^4.11 || 5 || ^5.0.0-beta.1" + } + }, + "node_modules/express/node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/express/node_modules/mime-db": { + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz", + "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/mime-types": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.0.tgz", + "integrity": "sha512-XqoSHeCGjVClAmoGFG3lVFqQFRIrTVw2OH3axRqAcfaw+gHWIfnASS92AV+Rl/mk0MupgZTRHQOjxY6YVnzK5w==", + "dependencies": { + "mime-db": "^1.53.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -16160,6 +16502,22 @@ "node": ">=8" } }, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", @@ -16287,6 +16645,14 @@ "node": ">= 12.20" } }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/framer-motion": { "version": "11.18.2", "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.18.2.tgz", @@ -16313,6 +16679,14 @@ } } }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -16390,16 +16764,20 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -16408,6 +16786,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-symbol-description": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", @@ -16543,12 +16933,11 @@ } }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -16608,10 +16997,9 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "engines": { "node": ">= 0.4" }, @@ -16726,6 +17114,21 @@ "entities": "^4.5.0" } }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/humanize-ms": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", @@ -16801,8 +17204,7 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/inline-style-parser": { "version": "0.2.3", @@ -16843,6 +17245,14 @@ "tslib": "^2.4.0" } }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/is-alphabetical": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", @@ -17173,6 +17583,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" + }, "node_modules/is-reference": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", @@ -17722,6 +18137,14 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/mdast-util-definitions": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz", @@ -18060,6 +18483,14 @@ "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", "peer": true }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/memoize-one": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", @@ -18070,6 +18501,17 @@ "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -18078,6 +18520,14 @@ "node": ">= 8" } }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/micromark": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", @@ -18794,6 +19244,14 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/next": { "version": "14.2.25", "resolved": "https://registry.npmjs.org/next/-/next-14.2.25.tgz", @@ -18976,10 +19434,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", - "dev": true, + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "engines": { "node": ">= 0.4" }, @@ -19101,11 +19558,21 @@ "node": "^10.13.0 || >=12.0.0" } }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "dependencies": { "wrappy": "1" } @@ -19373,6 +19840,14 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -19419,6 +19894,14 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "engines": { + "node": ">=16" + } + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -19475,6 +19958,14 @@ "node": ">= 6" } }, + "node_modules/pkce-challenge": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-4.1.0.tgz", + "integrity": "sha512-ZBmhE1C9LcPoH9XZSdwiPtbPHZROwAnMy+kIFQVrnMCxY4Cudlz3gBOpzilgc0jOgRaiT3sIWfpMomW2ar2orQ==", + "engines": { + "node": ">=16.20.0" + } + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -19653,6 +20144,18 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -19666,6 +20169,20 @@ "node": ">=6" } }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -19733,6 +20250,28 @@ "performance-now": "^2.1.0" } }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", @@ -20088,6 +20627,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/router": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.1.0.tgz", + "integrity": "sha512-/m/NSLxeYEgWNtyC+WtNHCF7jbGxOibVWKnn+1Psff4dJGOfoXP+MuC/f2CwSmyiHdOIzYnYFp4W6GxWfekaLA==", + "dependencies": { + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/rowboat-shared": { "version": "1.0.0", "resolved": "git+ssh://git@github.com/rowboatlabs/shared.git#1c8e722b8c5d644672a2db92f4ba5f25d8560352", @@ -20146,6 +20698,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/safe-regex-test": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", @@ -20200,6 +20771,55 @@ "node": ">=10" } }, + "node_modules/send": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.1.0.tgz", + "integrity": "sha512-v67WcEouB5GxbTWL/4NeToqcZiAWEq90N888fczVArY8A79J0L4FD7vj5hm3eUMua5EpoQ59wa/oovY6TLvRUA==", + "dependencies": { + "debug": "^4.3.5", + "destroy": "^1.2.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^0.5.2", + "http-errors": "^2.0.0", + "mime-types": "^2.1.35", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/send/node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.1.0.tgz", + "integrity": "sha512-A3We5UfEjG8Z7VkDv6uItWw6HY2bBSBJT1KtVESn6EOoOr2jAxNhxWCLY3jDE2WcuHXByWju74ck3ZgLwL8xmA==", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.0.0" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -20232,6 +20852,11 @@ "node": ">= 0.4" } }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, "node_modules/shallowequal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", @@ -20296,15 +20921,65 @@ } }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dev": true, + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -20385,6 +21060,14 @@ "svelte": "^4.0.0 || ^5.0.0-next.0" } }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/stop-iteration-iterator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", @@ -20940,6 +21623,14 @@ "node": ">=8.0" } }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, "node_modules/tr46": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", @@ -21046,6 +21737,38 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/type-is": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.0.tgz", + "integrity": "sha512-gd0sGezQYCbWSbkZr75mln4YBidWUN60+devscpLF5mtRDUpiaTvKpBNrdaCvel1NdR2k6vclXybU5fBd2i+nw==", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/mime-db": { + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz", + "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/mime-types": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.0.tgz", + "integrity": "sha512-XqoSHeCGjVClAmoGFG3lVFqQFRIrTVw2OH3axRqAcfaw+gHWIfnASS92AV+Rl/mk0MupgZTRHQOjxY6YVnzK5w==", + "dependencies": { + "mime-db": "^1.53.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", @@ -21280,6 +22003,14 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/update-browserslist-db": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", @@ -21374,6 +22105,14 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", @@ -21403,6 +22142,14 @@ "node": ">=8" } }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/vfile": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.2.tgz", @@ -21690,8 +22437,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/ws": { "version": "8.18.0", @@ -21744,19 +22490,19 @@ } }, "node_modules/zod": { - "version": "3.23.8", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", - "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "version": "3.24.2", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", + "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", "funding": { "url": "https://github.com/sponsors/colinhacks" } }, "node_modules/zod-to-json-schema": { - "version": "3.23.5", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.23.5.tgz", - "integrity": "sha512-5wlSS0bXfF/BrL4jPAbz9da5hDlDptdEppYfe+x4eIJ7jioqKG9uUxOwPzqof09u/XeVdrgFu29lZi+8XNDJtA==", + "version": "3.24.3", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.3.tgz", + "integrity": "sha512-HIAfWdYIt1sssHfYZFCXp4rU1w2r8hVVXYIlmoa0r0gABLs5di3RCqPU5DDROogVz1pAdYBaz7HK5n9pSUNs3A==", "peerDependencies": { - "zod": "^3.23.3" + "zod": "^3.24.1" } }, "node_modules/zwitch": { diff --git a/apps/rowboat/package.json b/apps/rowboat/package.json index 175e854d..0079ec9b 100644 --- a/apps/rowboat/package.json +++ b/apps/rowboat/package.json @@ -19,12 +19,13 @@ "@aws-sdk/s3-request-presigner": "^3.743.0", "@google/generative-ai": "^0.21.0", "@heroicons/react": "^2.2.0", - "@langchain/core": "^0.3.7", - "@langchain/textsplitters": "^0.1.0", - "@mendable/firecrawl-js": "^1.0.3", "@heroui/react": "2.7.4", "@heroui/system": "2.4.11", "@heroui/theme": "2.4.11", + "@langchain/core": "^0.3.7", + "@langchain/textsplitters": "^0.1.0", + "@mendable/firecrawl-js": "^1.0.3", + "@modelcontextprotocol/sdk": "^1.7.0", "@primer/react": "^36.27.0", "@qdrant/js-client-rest": "^1.13.0", "ai": "^3.3.28", @@ -72,4 +73,4 @@ "tsx": "^4.19.1", "typescript": "^5" } -} \ No newline at end of file +}