From 93217438ef7ee6857f38874af4da49036f5a88df Mon Sep 17 00:00:00 2001 From: "priyanshu.solanki" Date: Tue, 16 Dec 2025 17:07:14 -0700 Subject: [PATCH 01/27] added a workflow as mcp --- apps/sim/app/api/mcp/discover/route.ts | 134 +++ .../sim/app/api/mcp/serve/[serverId]/route.ts | 370 +++++++ .../app/api/mcp/serve/[serverId]/sse/route.ts | 422 ++++++++ .../[id]/connection-info/route.ts | 70 ++ .../workflow-servers/[id]/publish/route.ts | 148 +++ .../api/mcp/workflow-servers/[id]/route.ts | 155 +++ .../[id]/tools/[toolId]/route.ts | 178 ++++ .../mcp/workflow-servers/[id]/tools/route.ts | 253 +++++ .../sim/app/api/mcp/workflow-servers/route.ts | 107 ++ .../app/api/workflows/[id]/deploy/route.ts | 179 +++- .../deployments/[version]/activate/route.ts | 168 ++- .../deployments/[version]/revert/route.ts | 154 ++- .../app/api/workflows/[id]/execute/route.ts | 9 +- .../notifications/notifications.tsx | 8 +- .../components/logs-toolbar/logs-toolbar.tsx | 2 +- .../app/workspace/[workspaceId]/logs/utils.ts | 2 +- .../components/mcp-tool/mcp-tool.tsx | 817 +++++++++++++++ .../components/deploy-modal/deploy-modal.tsx | 15 +- .../settings-modal/components/index.ts | 1 + .../workflow-mcp-servers.tsx | 576 ++++++++++ .../settings-modal/settings-modal.tsx | 6 +- apps/sim/background/workflow-execution.ts | 2 +- apps/sim/hooks/queries/notifications.ts | 2 +- .../sim/hooks/queries/workflow-mcp-servers.ts | 554 ++++++++++ apps/sim/lib/core/rate-limiter/types.ts | 2 +- apps/sim/lib/execution/preprocessing.ts | 2 +- apps/sim/lib/logs/get-trigger-options.ts | 1 + apps/sim/lib/mcp/serve-auth.ts | 128 +++ apps/sim/lib/mcp/workflow-tool-schema.ts | 165 +++ apps/sim/stores/logs/filters/store.ts | 2 +- apps/sim/stores/logs/filters/types.ts | 2 +- .../db/migrations/0123_acoustic_hellcat.sql | 34 + .../db/migrations/meta/0123_snapshot.json | 986 ++++++++++++++---- packages/db/migrations/meta/_journal.json | 6 +- packages/db/schema.ts | 59 ++ 35 files changed, 5518 insertions(+), 201 deletions(-) create mode 100644 apps/sim/app/api/mcp/discover/route.ts create mode 100644 apps/sim/app/api/mcp/serve/[serverId]/route.ts create mode 100644 apps/sim/app/api/mcp/serve/[serverId]/sse/route.ts create mode 100644 apps/sim/app/api/mcp/workflow-servers/[id]/connection-info/route.ts create mode 100644 apps/sim/app/api/mcp/workflow-servers/[id]/publish/route.ts create mode 100644 apps/sim/app/api/mcp/workflow-servers/[id]/route.ts create mode 100644 apps/sim/app/api/mcp/workflow-servers/[id]/tools/[toolId]/route.ts create mode 100644 apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts create mode 100644 apps/sim/app/api/mcp/workflow-servers/route.ts create mode 100644 apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx create mode 100644 apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/workflow-mcp-servers/workflow-mcp-servers.tsx create mode 100644 apps/sim/hooks/queries/workflow-mcp-servers.ts create mode 100644 apps/sim/lib/mcp/serve-auth.ts create mode 100644 apps/sim/lib/mcp/workflow-tool-schema.ts create mode 100644 packages/db/migrations/0123_acoustic_hellcat.sql diff --git a/apps/sim/app/api/mcp/discover/route.ts b/apps/sim/app/api/mcp/discover/route.ts new file mode 100644 index 0000000000..775ebbf134 --- /dev/null +++ b/apps/sim/app/api/mcp/discover/route.ts @@ -0,0 +1,134 @@ +import { db } from '@sim/db' +import { permissions, workflowMcpServer, workspace } from '@sim/db/schema' +import { eq, and, sql } from 'drizzle-orm' +import { type NextRequest, NextResponse } from 'next/server' +import { checkHybridAuth } from '@/lib/auth/hybrid' +import { getBaseUrl } from '@/lib/core/utils/urls' +import { createLogger } from '@/lib/logs/console/logger' + +const logger = createLogger('McpDiscoverAPI') + +export const dynamic = 'force-dynamic' + +/** + * GET - Discover all published MCP servers available to the authenticated user + * + * This endpoint allows external MCP clients to discover available servers + * using just their API key, without needing to know workspace IDs. + * + * Authentication: API Key (X-API-Key header) or Session + * + * Returns all published MCP servers from workspaces the user has access to. + */ +export async function GET(request: NextRequest) { + try { + // Authenticate the request + const auth = await checkHybridAuth(request, { requireWorkflowId: false }) + + if (!auth.success || !auth.userId) { + return NextResponse.json( + { + success: false, + error: 'Authentication required. Provide X-API-Key header with your Sim API key.' + }, + { status: 401 } + ) + } + + const userId = auth.userId + + // Get all workspaces the user has access to via permissions table + const userWorkspacePermissions = await db + .select({ entityId: permissions.entityId }) + .from(permissions) + .where( + and( + eq(permissions.userId, userId), + eq(permissions.entityType, 'workspace') + ) + ) + + const workspaceIds = userWorkspacePermissions.map(w => w.entityId) + + if (workspaceIds.length === 0) { + return NextResponse.json({ + success: true, + servers: [], + message: 'No workspaces found for this user', + }) + } + + // Get all published MCP servers from user's workspaces with tool count + const servers = await db + .select({ + id: workflowMcpServer.id, + name: workflowMcpServer.name, + description: workflowMcpServer.description, + workspaceId: workflowMcpServer.workspaceId, + workspaceName: workspace.name, + isPublished: workflowMcpServer.isPublished, + publishedAt: workflowMcpServer.publishedAt, + toolCount: sql`( + SELECT COUNT(*)::int + FROM "workflow_mcp_tool" + WHERE "workflow_mcp_tool"."server_id" = "workflow_mcp_server"."id" + )`.as('tool_count'), + }) + .from(workflowMcpServer) + .leftJoin(workspace, eq(workflowMcpServer.workspaceId, workspace.id)) + .where( + and( + eq(workflowMcpServer.isPublished, true), + sql`${workflowMcpServer.workspaceId} IN ${workspaceIds}` + ) + ) + .orderBy(workflowMcpServer.name) + + const baseUrl = getBaseUrl() + + // Format response with connection URLs + const formattedServers = servers.map(server => ({ + id: server.id, + name: server.name, + description: server.description, + workspace: { + id: server.workspaceId, + name: server.workspaceName, + }, + toolCount: server.toolCount || 0, + publishedAt: server.publishedAt, + urls: { + http: `${baseUrl}/api/mcp/serve/${server.id}`, + sse: `${baseUrl}/api/mcp/serve/${server.id}/sse`, + }, + })) + + logger.info(`User ${userId} discovered ${formattedServers.length} MCP servers`) + + return NextResponse.json({ + success: true, + servers: formattedServers, + authentication: { + method: 'API Key', + header: 'X-API-Key', + description: 'Include your Sim API key in the X-API-Key header for all MCP requests', + }, + usage: { + listTools: { + method: 'POST', + body: '{"jsonrpc":"2.0","id":1,"method":"tools/list"}', + }, + callTool: { + method: 'POST', + body: '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"TOOL_NAME","arguments":{}}}', + }, + }, + }) + } catch (error) { + logger.error('Error discovering MCP servers:', error) + return NextResponse.json( + { success: false, error: 'Failed to discover MCP servers' }, + { status: 500 } + ) + } +} diff --git a/apps/sim/app/api/mcp/serve/[serverId]/route.ts b/apps/sim/app/api/mcp/serve/[serverId]/route.ts new file mode 100644 index 0000000000..e09890a39d --- /dev/null +++ b/apps/sim/app/api/mcp/serve/[serverId]/route.ts @@ -0,0 +1,370 @@ +import { db } from '@sim/db' +import { workflow, workflowMcpServer, workflowMcpTool } from '@sim/db/schema' +import { eq } from 'drizzle-orm' +import { type NextRequest, NextResponse } from 'next/server' +import { checkHybridAuth } from '@/lib/auth/hybrid' +import { getBaseUrl } from '@/lib/core/utils/urls' +import { createLogger } from '@/lib/logs/console/logger' + +const logger = createLogger('WorkflowMcpServeAPI') + +export const dynamic = 'force-dynamic' + +interface RouteParams { + serverId: string +} + +/** + * MCP JSON-RPC Request + */ +interface JsonRpcRequest { + jsonrpc: '2.0' + id: string | number + method: string + params?: Record +} + +/** + * MCP JSON-RPC Response + */ +interface JsonRpcResponse { + jsonrpc: '2.0' + id: string | number + result?: unknown + error?: { + code: number + message: string + data?: unknown + } +} + +/** + * Create JSON-RPC success response + */ +function createJsonRpcResponse(id: string | number, result: unknown): JsonRpcResponse { + return { + jsonrpc: '2.0', + id, + result, + } +} + +/** + * Create JSON-RPC error response + */ +function createJsonRpcError( + id: string | number, + code: number, + message: string, + data?: unknown +): JsonRpcResponse { + return { + jsonrpc: '2.0', + id, + error: { code, message, data }, + } +} + +/** + * Validate that the server exists and is published + */ +async function validateServer(serverId: string) { + const [server] = await db + .select({ + id: workflowMcpServer.id, + name: workflowMcpServer.name, + workspaceId: workflowMcpServer.workspaceId, + isPublished: workflowMcpServer.isPublished, + }) + .from(workflowMcpServer) + .where(eq(workflowMcpServer.id, serverId)) + .limit(1) + + return server +} + +/** + * GET - Server info and capabilities (MCP initialize) + */ +export async function GET( + request: NextRequest, + { params }: { params: Promise } +) { + const { serverId } = await params + + try { + const server = await validateServer(serverId) + + if (!server) { + return NextResponse.json({ error: 'Server not found' }, { status: 404 }) + } + + if (!server.isPublished) { + return NextResponse.json({ error: 'Server is not published' }, { status: 403 }) + } + + // Return server capabilities + return NextResponse.json({ + name: server.name, + version: '1.0.0', + protocolVersion: '2024-11-05', + capabilities: { + tools: {}, + }, + instructions: `This MCP server exposes workflow tools from Sim Studio. Each tool executes a deployed workflow.`, + }) + } catch (error) { + logger.error('Error getting MCP server info:', error) + return NextResponse.json({ error: 'Internal server error' }, { status: 500 }) + } +} + +/** + * POST - Handle MCP JSON-RPC requests + */ +export async function POST( + request: NextRequest, + { params }: { params: Promise } +) { + const { serverId } = await params + + try { + // Validate server + const server = await validateServer(serverId) + + if (!server) { + return NextResponse.json({ error: 'Server not found' }, { status: 404 }) + } + + if (!server.isPublished) { + return NextResponse.json({ error: 'Server is not published' }, { status: 403 }) + } + + // Authenticate the request + const auth = await checkHybridAuth(request, { requireWorkflowId: false }) + if (!auth.success || !auth.userId) { + return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) + } + + // Parse JSON-RPC request + const body = await request.json() + const rpcRequest = body as JsonRpcRequest + + if (rpcRequest.jsonrpc !== '2.0' || !rpcRequest.method) { + return NextResponse.json( + createJsonRpcError(rpcRequest?.id || 0, -32600, 'Invalid Request'), + { status: 400 } + ) + } + + // Handle different MCP methods + switch (rpcRequest.method) { + case 'initialize': + return NextResponse.json( + createJsonRpcResponse(rpcRequest.id, { + protocolVersion: '2024-11-05', + capabilities: { + tools: {}, + }, + serverInfo: { + name: server.name, + version: '1.0.0', + }, + }) + ) + + case 'tools/list': + return handleToolsList(rpcRequest, serverId) + + case 'tools/call': { + // Get the API key from the request to forward to the workflow execute call + const apiKey = request.headers.get('X-API-Key') || request.headers.get('Authorization')?.replace('Bearer ', '') + return handleToolsCall(rpcRequest, serverId, auth.userId, server.workspaceId, apiKey) + } + + case 'ping': + return NextResponse.json(createJsonRpcResponse(rpcRequest.id, {})) + + default: + return NextResponse.json( + createJsonRpcError(rpcRequest.id, -32601, `Method not found: ${rpcRequest.method}`), + { status: 404 } + ) + } + } catch (error) { + logger.error('Error handling MCP request:', error) + return NextResponse.json( + createJsonRpcError(0, -32603, 'Internal error'), + { status: 500 } + ) + } +} + +/** + * Handle tools/list method + */ +async function handleToolsList( + rpcRequest: JsonRpcRequest, + serverId: string +): Promise { + try { + const tools = await db + .select({ + id: workflowMcpTool.id, + toolName: workflowMcpTool.toolName, + toolDescription: workflowMcpTool.toolDescription, + parameterSchema: workflowMcpTool.parameterSchema, + isEnabled: workflowMcpTool.isEnabled, + workflowId: workflowMcpTool.workflowId, + }) + .from(workflowMcpTool) + .where(eq(workflowMcpTool.serverId, serverId)) + + const mcpTools = tools + .filter((tool) => tool.isEnabled) + .map((tool) => ({ + name: tool.toolName, + description: tool.toolDescription || `Execute workflow tool: ${tool.toolName}`, + inputSchema: tool.parameterSchema || { + type: 'object', + properties: { + input: { + type: 'object', + description: 'Input data for the workflow', + }, + }, + }, + })) + + return NextResponse.json( + createJsonRpcResponse(rpcRequest.id, { tools: mcpTools }) + ) + } catch (error) { + logger.error('Error listing tools:', error) + return NextResponse.json( + createJsonRpcError(rpcRequest.id, -32603, 'Failed to list tools'), + { status: 500 } + ) + } +} + +/** + * Handle tools/call method + */ +async function handleToolsCall( + rpcRequest: JsonRpcRequest, + serverId: string, + userId: string, + workspaceId: string, + apiKey?: string | null +): Promise { + try { + const params = rpcRequest.params as { name: string; arguments?: Record } | undefined + + if (!params?.name) { + return NextResponse.json( + createJsonRpcError(rpcRequest.id, -32602, 'Invalid params: tool name required'), + { status: 400 } + ) + } + + // Find the tool + const [tool] = await db + .select({ + id: workflowMcpTool.id, + toolName: workflowMcpTool.toolName, + workflowId: workflowMcpTool.workflowId, + isEnabled: workflowMcpTool.isEnabled, + }) + .from(workflowMcpTool) + .where(eq(workflowMcpTool.serverId, serverId)) + .then((tools) => tools.filter((t) => t.toolName === params.name)) + + if (!tool) { + return NextResponse.json( + createJsonRpcError(rpcRequest.id, -32602, `Tool not found: ${params.name}`), + { status: 404 } + ) + } + + if (!tool.isEnabled) { + return NextResponse.json( + createJsonRpcError(rpcRequest.id, -32602, `Tool is disabled: ${params.name}`), + { status: 400 } + ) + } + + // Verify workflow is still deployed + const [workflowRecord] = await db + .select({ id: workflow.id, isDeployed: workflow.isDeployed }) + .from(workflow) + .where(eq(workflow.id, tool.workflowId)) + .limit(1) + + if (!workflowRecord || !workflowRecord.isDeployed) { + return NextResponse.json( + createJsonRpcError(rpcRequest.id, -32603, 'Workflow is not deployed'), + { status: 400 } + ) + } + + // Execute the workflow + const baseUrl = getBaseUrl() + const executeUrl = `${baseUrl}/api/workflows/${tool.workflowId}/execute` + + logger.info(`Executing workflow ${tool.workflowId} via MCP tool ${params.name}`) + + // Build headers for the internal execute call + const executeHeaders: Record = { + 'Content-Type': 'application/json', + } + + // Forward the API key for authentication + if (apiKey) { + executeHeaders['X-API-Key'] = apiKey + } + + const executeResponse = await fetch(executeUrl, { + method: 'POST', + headers: executeHeaders, + body: JSON.stringify({ + input: params.arguments || {}, + triggerType: 'mcp', + }), + }) + + const executeResult = await executeResponse.json() + + if (!executeResponse.ok) { + return NextResponse.json( + createJsonRpcError( + rpcRequest.id, + -32603, + executeResult.error || 'Workflow execution failed' + ), + { status: 500 } + ) + } + + // Format response for MCP + const content = [ + { + type: 'text', + text: JSON.stringify(executeResult.output || executeResult, null, 2), + }, + ] + + return NextResponse.json( + createJsonRpcResponse(rpcRequest.id, { + content, + isError: !executeResult.success, + }) + ) + } catch (error) { + logger.error('Error calling tool:', error) + return NextResponse.json( + createJsonRpcError(rpcRequest.id, -32603, 'Tool execution failed'), + { status: 500 } + ) + } +} diff --git a/apps/sim/app/api/mcp/serve/[serverId]/sse/route.ts b/apps/sim/app/api/mcp/serve/[serverId]/sse/route.ts new file mode 100644 index 0000000000..0fddff9cbc --- /dev/null +++ b/apps/sim/app/api/mcp/serve/[serverId]/sse/route.ts @@ -0,0 +1,422 @@ +import { db } from '@sim/db' +import { workflow, workflowMcpServer, workflowMcpTool } from '@sim/db/schema' +import { eq } from 'drizzle-orm' +import { type NextRequest, NextResponse } from 'next/server' +import { checkHybridAuth } from '@/lib/auth/hybrid' +import { getBaseUrl } from '@/lib/core/utils/urls' +import { SSE_HEADERS } from '@/lib/core/utils/sse' +import { createLogger } from '@/lib/logs/console/logger' + +const logger = createLogger('WorkflowMcpSSE') + +export const dynamic = 'force-dynamic' +export const runtime = 'nodejs' + +interface RouteParams { + serverId: string +} + +/** + * MCP JSON-RPC Request/Response types + */ +interface JsonRpcMessage { + jsonrpc: '2.0' + id?: string | number + method?: string + params?: Record + result?: unknown + error?: { + code: number + message: string + data?: unknown + } +} + +/** + * Validate that the server exists and is published + */ +async function validateServer(serverId: string) { + const [server] = await db + .select({ + id: workflowMcpServer.id, + name: workflowMcpServer.name, + workspaceId: workflowMcpServer.workspaceId, + isPublished: workflowMcpServer.isPublished, + }) + .from(workflowMcpServer) + .where(eq(workflowMcpServer.id, serverId)) + .limit(1) + + return server +} + +/** + * GET - SSE endpoint for MCP protocol + * This establishes a Server-Sent Events connection for bidirectional MCP communication + */ +export async function GET( + request: NextRequest, + { params }: { params: Promise } +) { + const { serverId } = await params + + try { + // Validate server exists and is published + const server = await validateServer(serverId) + + if (!server) { + return NextResponse.json({ error: 'Server not found' }, { status: 404 }) + } + + if (!server.isPublished) { + return NextResponse.json({ error: 'Server is not published' }, { status: 403 }) + } + + // Check authentication + const auth = await checkHybridAuth(request, { requireWorkflowId: false }) + if (!auth.success || !auth.userId) { + return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) + } + + const userId = auth.userId + const workspaceId = server.workspaceId + + // Create SSE stream + const encoder = new TextEncoder() + let isStreamClosed = false + + const stream = new ReadableStream({ + async start(controller) { + const sendEvent = (event: string, data: unknown) => { + if (isStreamClosed) return + try { + const message = `event: ${event}\ndata: ${JSON.stringify(data)}\n\n` + controller.enqueue(encoder.encode(message)) + } catch { + isStreamClosed = true + } + } + + // Send initial connection event + sendEvent('open', { type: 'connection', status: 'connected' }) + + // Send server capabilities + sendEvent('message', { + jsonrpc: '2.0', + method: 'notifications/initialized', + params: { + protocolVersion: '2024-11-05', + capabilities: { + tools: {}, + }, + serverInfo: { + name: server.name, + version: '1.0.0', + }, + }, + }) + + // Keep connection alive with periodic pings + const pingInterval = setInterval(() => { + if (isStreamClosed) { + clearInterval(pingInterval) + return + } + sendEvent('ping', { timestamp: Date.now() }) + }, 30000) + + // Handle cleanup + request.signal.addEventListener('abort', () => { + isStreamClosed = true + clearInterval(pingInterval) + try { + controller.close() + } catch { + // Stream already closed + } + }) + }, + + cancel() { + isStreamClosed = true + logger.info(`SSE connection closed for server ${serverId}`) + }, + }) + + return new NextResponse(stream, { + headers: { + ...SSE_HEADERS, + 'X-MCP-Server-Id': serverId, + 'X-MCP-Server-Name': server.name, + }, + }) + } catch (error) { + logger.error('Error establishing SSE connection:', error) + return NextResponse.json({ error: 'Internal server error' }, { status: 500 }) + } +} + +/** + * POST - Handle messages sent to the SSE endpoint + * This is used for the message channel in MCP streamable-http transport + */ +export async function POST( + request: NextRequest, + { params }: { params: Promise } +) { + const { serverId } = await params + + try { + // Validate server + const server = await validateServer(serverId) + + if (!server) { + return NextResponse.json({ error: 'Server not found' }, { status: 404 }) + } + + if (!server.isPublished) { + return NextResponse.json({ error: 'Server is not published' }, { status: 403 }) + } + + // Check authentication + const auth = await checkHybridAuth(request, { requireWorkflowId: false }) + if (!auth.success || !auth.userId) { + return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) + } + + const userId = auth.userId + const workspaceId = server.workspaceId + + // Parse the incoming message + const message = (await request.json()) as JsonRpcMessage + + if (message.jsonrpc !== '2.0') { + return NextResponse.json( + { + jsonrpc: '2.0', + id: message.id || 0, + error: { code: -32600, message: 'Invalid Request' }, + }, + { status: 400 } + ) + } + + // Handle different methods + switch (message.method) { + case 'initialize': + return NextResponse.json({ + jsonrpc: '2.0', + id: message.id, + result: { + protocolVersion: '2024-11-05', + capabilities: { + tools: {}, + }, + serverInfo: { + name: server.name, + version: '1.0.0', + }, + }, + }) + + case 'tools/list': + return handleToolsList(message.id!, serverId) + + case 'tools/call': { + // Get the API key from the request to forward to the workflow execute call + const apiKey = request.headers.get('X-API-Key') || request.headers.get('Authorization')?.replace('Bearer ', '') + return handleToolsCall(message, serverId, userId, workspaceId, apiKey) + } + + case 'ping': + return NextResponse.json({ + jsonrpc: '2.0', + id: message.id, + result: {}, + }) + + default: + return NextResponse.json({ + jsonrpc: '2.0', + id: message.id || 0, + error: { code: -32601, message: `Method not found: ${message.method}` }, + }) + } + } catch (error) { + logger.error('Error handling SSE POST:', error) + return NextResponse.json( + { + jsonrpc: '2.0', + id: 0, + error: { code: -32603, message: 'Internal error' }, + }, + { status: 500 } + ) + } +} + +/** + * Handle tools/list method + */ +async function handleToolsList( + id: string | number, + serverId: string +): Promise { + const tools = await db + .select({ + toolName: workflowMcpTool.toolName, + toolDescription: workflowMcpTool.toolDescription, + parameterSchema: workflowMcpTool.parameterSchema, + isEnabled: workflowMcpTool.isEnabled, + }) + .from(workflowMcpTool) + .where(eq(workflowMcpTool.serverId, serverId)) + + const mcpTools = tools + .filter((tool) => tool.isEnabled) + .map((tool) => ({ + name: tool.toolName, + description: tool.toolDescription || `Execute workflow tool: ${tool.toolName}`, + inputSchema: tool.parameterSchema || { + type: 'object', + properties: { + input: { + type: 'object', + description: 'Input data for the workflow', + }, + }, + }, + })) + + return NextResponse.json({ + jsonrpc: '2.0', + id, + result: { tools: mcpTools }, + }) +} + +/** + * Handle tools/call method + */ +async function handleToolsCall( + message: JsonRpcMessage, + serverId: string, + userId: string, + workspaceId: string, + apiKey?: string | null +): Promise { + const params = message.params as { name: string; arguments?: Record } | undefined + + if (!params?.name) { + return NextResponse.json({ + jsonrpc: '2.0', + id: message.id || 0, + error: { code: -32602, message: 'Invalid params: tool name required' }, + }) + } + + // Find the tool + const tools = await db + .select({ + toolName: workflowMcpTool.toolName, + workflowId: workflowMcpTool.workflowId, + isEnabled: workflowMcpTool.isEnabled, + }) + .from(workflowMcpTool) + .where(eq(workflowMcpTool.serverId, serverId)) + + const tool = tools.find((t) => t.toolName === params.name) + + if (!tool) { + return NextResponse.json({ + jsonrpc: '2.0', + id: message.id || 0, + error: { code: -32602, message: `Tool not found: ${params.name}` }, + }) + } + + if (!tool.isEnabled) { + return NextResponse.json({ + jsonrpc: '2.0', + id: message.id || 0, + error: { code: -32602, message: `Tool is disabled: ${params.name}` }, + }) + } + + // Verify workflow is deployed + const [workflowRecord] = await db + .select({ id: workflow.id, isDeployed: workflow.isDeployed }) + .from(workflow) + .where(eq(workflow.id, tool.workflowId)) + .limit(1) + + if (!workflowRecord || !workflowRecord.isDeployed) { + return NextResponse.json({ + jsonrpc: '2.0', + id: message.id || 0, + error: { code: -32603, message: 'Workflow is not deployed' }, + }) + } + + // Execute the workflow + const baseUrl = getBaseUrl() + const executeUrl = `${baseUrl}/api/workflows/${tool.workflowId}/execute` + + logger.info(`Executing workflow ${tool.workflowId} via MCP SSE tool ${params.name}`) + + try { + // Build headers for the internal execute call + const executeHeaders: Record = { + 'Content-Type': 'application/json', + } + + // Forward the API key for authentication + if (apiKey) { + executeHeaders['X-API-Key'] = apiKey + } + + const executeResponse = await fetch(executeUrl, { + method: 'POST', + headers: executeHeaders, + body: JSON.stringify({ + input: params.arguments || {}, + triggerType: 'mcp', + }), + }) + + const executeResult = await executeResponse.json() + + if (!executeResponse.ok) { + return NextResponse.json({ + jsonrpc: '2.0', + id: message.id || 0, + error: { + code: -32603, + message: executeResult.error || 'Workflow execution failed', + }, + }) + } + + // Format response for MCP + return NextResponse.json({ + jsonrpc: '2.0', + id: message.id, + result: { + content: [ + { + type: 'text', + text: JSON.stringify(executeResult.output || executeResult, null, 2), + }, + ], + isError: !executeResult.success, + }, + }) + } catch (error) { + logger.error('Error executing workflow:', error) + return NextResponse.json({ + jsonrpc: '2.0', + id: message.id || 0, + error: { code: -32603, message: 'Tool execution failed' }, + }) + } +} diff --git a/apps/sim/app/api/mcp/workflow-servers/[id]/connection-info/route.ts b/apps/sim/app/api/mcp/workflow-servers/[id]/connection-info/route.ts new file mode 100644 index 0000000000..5d0c6766c7 --- /dev/null +++ b/apps/sim/app/api/mcp/workflow-servers/[id]/connection-info/route.ts @@ -0,0 +1,70 @@ +import { db } from '@sim/db' +import { workflowMcpServer } from '@sim/db/schema' +import { and, eq } from 'drizzle-orm' +import type { NextRequest } from 'next/server' +import { getBaseUrl } from '@/lib/core/utils/urls' +import { createLogger } from '@/lib/logs/console/logger' +import { withMcpAuth } from '@/lib/mcp/middleware' +import { getMcpServerConnectionInfo } from '@/lib/mcp/serve-auth' +import { createMcpErrorResponse, createMcpSuccessResponse } from '@/lib/mcp/utils' + +const logger = createLogger('WorkflowMcpConnectionInfoAPI') + +export const dynamic = 'force-dynamic' + +interface RouteParams { + id: string +} + +/** + * GET - Get connection info for an MCP server + */ +export const GET = withMcpAuth('read')( + async (request: NextRequest, { userId, workspaceId, requestId }, { params }) => { + try { + const { id: serverId } = await params + + logger.info(`[${requestId}] Getting connection info for server: ${serverId}`) + + const [server] = await db + .select({ + id: workflowMcpServer.id, + name: workflowMcpServer.name, + isPublished: workflowMcpServer.isPublished, + }) + .from(workflowMcpServer) + .where( + and(eq(workflowMcpServer.id, serverId), eq(workflowMcpServer.workspaceId, workspaceId)) + ) + .limit(1) + + if (!server) { + return createMcpErrorResponse(new Error('Server not found'), 'Server not found', 404) + } + + if (!server.isPublished) { + return createMcpErrorResponse( + new Error('Server must be published to get connection info'), + 'Server not published', + 400 + ) + } + + const baseUrl = getBaseUrl() + const connectionInfo = getMcpServerConnectionInfo(serverId, server.name, baseUrl) + + return createMcpSuccessResponse({ + serverId, + serverName: server.name, + ...connectionInfo, + }) + } catch (error) { + logger.error(`[${requestId}] Error getting connection info:`, error) + return createMcpErrorResponse( + error instanceof Error ? error : new Error('Failed to get connection info'), + 'Failed to get connection info', + 500 + ) + } + } +) diff --git a/apps/sim/app/api/mcp/workflow-servers/[id]/publish/route.ts b/apps/sim/app/api/mcp/workflow-servers/[id]/publish/route.ts new file mode 100644 index 0000000000..9980c43ef8 --- /dev/null +++ b/apps/sim/app/api/mcp/workflow-servers/[id]/publish/route.ts @@ -0,0 +1,148 @@ +import { db } from '@sim/db' +import { workflowMcpServer, workflowMcpTool } from '@sim/db/schema' +import { and, eq } from 'drizzle-orm' +import type { NextRequest } from 'next/server' +import { getBaseUrl } from '@/lib/core/utils/urls' +import { createLogger } from '@/lib/logs/console/logger' +import { withMcpAuth } from '@/lib/mcp/middleware' +import { createMcpErrorResponse, createMcpSuccessResponse } from '@/lib/mcp/utils' + +const logger = createLogger('WorkflowMcpServerPublishAPI') + +export const dynamic = 'force-dynamic' + +interface RouteParams { + id: string +} + +/** + * POST - Publish a workflow MCP server (make it accessible via OAuth) + */ +export const POST = withMcpAuth('admin')( + async (request: NextRequest, { userId, workspaceId, requestId }, { params }) => { + try { + const { id: serverId } = await params + + logger.info(`[${requestId}] Publishing workflow MCP server: ${serverId}`) + + const [existingServer] = await db + .select({ id: workflowMcpServer.id, isPublished: workflowMcpServer.isPublished }) + .from(workflowMcpServer) + .where( + and(eq(workflowMcpServer.id, serverId), eq(workflowMcpServer.workspaceId, workspaceId)) + ) + .limit(1) + + if (!existingServer) { + return createMcpErrorResponse(new Error('Server not found'), 'Server not found', 404) + } + + if (existingServer.isPublished) { + return createMcpErrorResponse( + new Error('Server is already published'), + 'Server is already published', + 400 + ) + } + + // Check if server has at least one tool + const tools = await db + .select({ id: workflowMcpTool.id }) + .from(workflowMcpTool) + .where(eq(workflowMcpTool.serverId, serverId)) + .limit(1) + + if (tools.length === 0) { + return createMcpErrorResponse( + new Error('Cannot publish server without any tools. Add at least one workflow as a tool first.'), + 'Server has no tools', + 400 + ) + } + + const [updatedServer] = await db + .update(workflowMcpServer) + .set({ + isPublished: true, + publishedAt: new Date(), + updatedAt: new Date(), + }) + .where(eq(workflowMcpServer.id, serverId)) + .returning() + + const baseUrl = getBaseUrl() + const mcpServerUrl = `${baseUrl}/api/mcp/serve/${serverId}/sse` + + logger.info(`[${requestId}] Successfully published workflow MCP server: ${serverId}`) + + return createMcpSuccessResponse({ + server: updatedServer, + mcpServerUrl, + message: 'Server published successfully. External MCP clients can now connect using OAuth.', + }) + } catch (error) { + logger.error(`[${requestId}] Error publishing workflow MCP server:`, error) + return createMcpErrorResponse( + error instanceof Error ? error : new Error('Failed to publish workflow MCP server'), + 'Failed to publish workflow MCP server', + 500 + ) + } + } +) + +/** + * DELETE - Unpublish a workflow MCP server + */ +export const DELETE = withMcpAuth('admin')( + async (request: NextRequest, { userId, workspaceId, requestId }, { params }) => { + try { + const { id: serverId } = await params + + logger.info(`[${requestId}] Unpublishing workflow MCP server: ${serverId}`) + + const [existingServer] = await db + .select({ id: workflowMcpServer.id, isPublished: workflowMcpServer.isPublished }) + .from(workflowMcpServer) + .where( + and(eq(workflowMcpServer.id, serverId), eq(workflowMcpServer.workspaceId, workspaceId)) + ) + .limit(1) + + if (!existingServer) { + return createMcpErrorResponse(new Error('Server not found'), 'Server not found', 404) + } + + if (!existingServer.isPublished) { + return createMcpErrorResponse( + new Error('Server is not published'), + 'Server is not published', + 400 + ) + } + + const [updatedServer] = await db + .update(workflowMcpServer) + .set({ + isPublished: false, + updatedAt: new Date(), + }) + .where(eq(workflowMcpServer.id, serverId)) + .returning() + + logger.info(`[${requestId}] Successfully unpublished workflow MCP server: ${serverId}`) + + return createMcpSuccessResponse({ + server: updatedServer, + message: 'Server unpublished successfully. External MCP clients can no longer connect.', + }) + } catch (error) { + logger.error(`[${requestId}] Error unpublishing workflow MCP server:`, error) + return createMcpErrorResponse( + error instanceof Error ? error : new Error('Failed to unpublish workflow MCP server'), + 'Failed to unpublish workflow MCP server', + 500 + ) + } + } +) diff --git a/apps/sim/app/api/mcp/workflow-servers/[id]/route.ts b/apps/sim/app/api/mcp/workflow-servers/[id]/route.ts new file mode 100644 index 0000000000..91ffb7760d --- /dev/null +++ b/apps/sim/app/api/mcp/workflow-servers/[id]/route.ts @@ -0,0 +1,155 @@ +import { db } from '@sim/db' +import { workflowMcpServer, workflowMcpTool } from '@sim/db/schema' +import { and, eq, sql } from 'drizzle-orm' +import type { NextRequest } from 'next/server' +import { createLogger } from '@/lib/logs/console/logger' +import { getParsedBody, withMcpAuth } from '@/lib/mcp/middleware' +import { createMcpErrorResponse, createMcpSuccessResponse } from '@/lib/mcp/utils' + +const logger = createLogger('WorkflowMcpServerAPI') + +export const dynamic = 'force-dynamic' + +interface RouteParams { + id: string +} + +/** + * GET - Get a specific workflow MCP server with its tools + */ +export const GET = withMcpAuth('read')( + async (request: NextRequest, { userId, workspaceId, requestId }, { params }) => { + try { + const { id: serverId } = await params + + logger.info(`[${requestId}] Getting workflow MCP server: ${serverId}`) + + const [server] = await db + .select({ + id: workflowMcpServer.id, + workspaceId: workflowMcpServer.workspaceId, + createdBy: workflowMcpServer.createdBy, + name: workflowMcpServer.name, + description: workflowMcpServer.description, + isPublished: workflowMcpServer.isPublished, + publishedAt: workflowMcpServer.publishedAt, + createdAt: workflowMcpServer.createdAt, + updatedAt: workflowMcpServer.updatedAt, + }) + .from(workflowMcpServer) + .where( + and(eq(workflowMcpServer.id, serverId), eq(workflowMcpServer.workspaceId, workspaceId)) + ) + .limit(1) + + if (!server) { + return createMcpErrorResponse(new Error('Server not found'), 'Server not found', 404) + } + + const tools = await db + .select() + .from(workflowMcpTool) + .where(eq(workflowMcpTool.serverId, serverId)) + + logger.info(`[${requestId}] Found workflow MCP server: ${server.name} with ${tools.length} tools`) + + return createMcpSuccessResponse({ server, tools }) + } catch (error) { + logger.error(`[${requestId}] Error getting workflow MCP server:`, error) + return createMcpErrorResponse( + error instanceof Error ? error : new Error('Failed to get workflow MCP server'), + 'Failed to get workflow MCP server', + 500 + ) + } + } +) + +/** + * PATCH - Update a workflow MCP server + */ +export const PATCH = withMcpAuth('write')( + async (request: NextRequest, { userId, workspaceId, requestId }, { params }) => { + try { + const { id: serverId } = await params + const body = getParsedBody(request) || (await request.json()) + + logger.info(`[${requestId}] Updating workflow MCP server: ${serverId}`) + + const [existingServer] = await db + .select({ id: workflowMcpServer.id }) + .from(workflowMcpServer) + .where( + and(eq(workflowMcpServer.id, serverId), eq(workflowMcpServer.workspaceId, workspaceId)) + ) + .limit(1) + + if (!existingServer) { + return createMcpErrorResponse(new Error('Server not found'), 'Server not found', 404) + } + + const updateData: Record = { + updatedAt: new Date(), + } + + if (body.name !== undefined) { + updateData.name = body.name.trim() + } + if (body.description !== undefined) { + updateData.description = body.description?.trim() || null + } + + const [updatedServer] = await db + .update(workflowMcpServer) + .set(updateData) + .where(eq(workflowMcpServer.id, serverId)) + .returning() + + logger.info(`[${requestId}] Successfully updated workflow MCP server: ${serverId}`) + + return createMcpSuccessResponse({ server: updatedServer }) + } catch (error) { + logger.error(`[${requestId}] Error updating workflow MCP server:`, error) + return createMcpErrorResponse( + error instanceof Error ? error : new Error('Failed to update workflow MCP server'), + 'Failed to update workflow MCP server', + 500 + ) + } + } +) + +/** + * DELETE - Delete a workflow MCP server and all its tools + */ +export const DELETE = withMcpAuth('admin')( + async (request: NextRequest, { userId, workspaceId, requestId }, { params }) => { + try { + const { id: serverId } = await params + + logger.info(`[${requestId}] Deleting workflow MCP server: ${serverId}`) + + const [deletedServer] = await db + .delete(workflowMcpServer) + .where( + and(eq(workflowMcpServer.id, serverId), eq(workflowMcpServer.workspaceId, workspaceId)) + ) + .returning() + + if (!deletedServer) { + return createMcpErrorResponse(new Error('Server not found'), 'Server not found', 404) + } + + logger.info(`[${requestId}] Successfully deleted workflow MCP server: ${serverId}`) + + return createMcpSuccessResponse({ message: `Server ${serverId} deleted successfully` }) + } catch (error) { + logger.error(`[${requestId}] Error deleting workflow MCP server:`, error) + return createMcpErrorResponse( + error instanceof Error ? error : new Error('Failed to delete workflow MCP server'), + 'Failed to delete workflow MCP server', + 500 + ) + } + } +) diff --git a/apps/sim/app/api/mcp/workflow-servers/[id]/tools/[toolId]/route.ts b/apps/sim/app/api/mcp/workflow-servers/[id]/tools/[toolId]/route.ts new file mode 100644 index 0000000000..eda9affb30 --- /dev/null +++ b/apps/sim/app/api/mcp/workflow-servers/[id]/tools/[toolId]/route.ts @@ -0,0 +1,178 @@ +import { db } from '@sim/db' +import { workflowMcpServer, workflowMcpTool } from '@sim/db/schema' +import { and, eq } from 'drizzle-orm' +import type { NextRequest } from 'next/server' +import { createLogger } from '@/lib/logs/console/logger' +import { getParsedBody, withMcpAuth } from '@/lib/mcp/middleware' +import { createMcpErrorResponse, createMcpSuccessResponse } from '@/lib/mcp/utils' + +const logger = createLogger('WorkflowMcpToolAPI') + +export const dynamic = 'force-dynamic' + +interface RouteParams { + id: string + toolId: string +} + +/** + * GET - Get a specific tool + */ +export const GET = withMcpAuth('read')( + async (request: NextRequest, { userId, workspaceId, requestId }, { params }) => { + try { + const { id: serverId, toolId } = await params + + logger.info(`[${requestId}] Getting tool ${toolId} from server ${serverId}`) + + // Verify server exists and belongs to workspace + const [server] = await db + .select({ id: workflowMcpServer.id }) + .from(workflowMcpServer) + .where( + and(eq(workflowMcpServer.id, serverId), eq(workflowMcpServer.workspaceId, workspaceId)) + ) + .limit(1) + + if (!server) { + return createMcpErrorResponse(new Error('Server not found'), 'Server not found', 404) + } + + const [tool] = await db + .select() + .from(workflowMcpTool) + .where(and(eq(workflowMcpTool.id, toolId), eq(workflowMcpTool.serverId, serverId))) + .limit(1) + + if (!tool) { + return createMcpErrorResponse(new Error('Tool not found'), 'Tool not found', 404) + } + + return createMcpSuccessResponse({ tool }) + } catch (error) { + logger.error(`[${requestId}] Error getting tool:`, error) + return createMcpErrorResponse( + error instanceof Error ? error : new Error('Failed to get tool'), + 'Failed to get tool', + 500 + ) + } + } +) + +/** + * PATCH - Update a tool's configuration + */ +export const PATCH = withMcpAuth('write')( + async (request: NextRequest, { userId, workspaceId, requestId }, { params }) => { + try { + const { id: serverId, toolId } = await params + const body = getParsedBody(request) || (await request.json()) + + logger.info(`[${requestId}] Updating tool ${toolId} in server ${serverId}`) + + // Verify server exists and belongs to workspace + const [server] = await db + .select({ id: workflowMcpServer.id }) + .from(workflowMcpServer) + .where( + and(eq(workflowMcpServer.id, serverId), eq(workflowMcpServer.workspaceId, workspaceId)) + ) + .limit(1) + + if (!server) { + return createMcpErrorResponse(new Error('Server not found'), 'Server not found', 404) + } + + const [existingTool] = await db + .select({ id: workflowMcpTool.id }) + .from(workflowMcpTool) + .where(and(eq(workflowMcpTool.id, toolId), eq(workflowMcpTool.serverId, serverId))) + .limit(1) + + if (!existingTool) { + return createMcpErrorResponse(new Error('Tool not found'), 'Tool not found', 404) + } + + const updateData: Record = { + updatedAt: new Date(), + } + + if (body.toolName !== undefined) { + updateData.toolName = body.toolName.trim() + } + if (body.toolDescription !== undefined) { + updateData.toolDescription = body.toolDescription?.trim() || null + } + if (body.parameterSchema !== undefined) { + updateData.parameterSchema = body.parameterSchema + } + if (body.isEnabled !== undefined) { + updateData.isEnabled = body.isEnabled + } + + const [updatedTool] = await db + .update(workflowMcpTool) + .set(updateData) + .where(eq(workflowMcpTool.id, toolId)) + .returning() + + logger.info(`[${requestId}] Successfully updated tool ${toolId}`) + + return createMcpSuccessResponse({ tool: updatedTool }) + } catch (error) { + logger.error(`[${requestId}] Error updating tool:`, error) + return createMcpErrorResponse( + error instanceof Error ? error : new Error('Failed to update tool'), + 'Failed to update tool', + 500 + ) + } + } +) + +/** + * DELETE - Remove a tool from an MCP server + */ +export const DELETE = withMcpAuth('write')( + async (request: NextRequest, { userId, workspaceId, requestId }, { params }) => { + try { + const { id: serverId, toolId } = await params + + logger.info(`[${requestId}] Deleting tool ${toolId} from server ${serverId}`) + + // Verify server exists and belongs to workspace + const [server] = await db + .select({ id: workflowMcpServer.id }) + .from(workflowMcpServer) + .where( + and(eq(workflowMcpServer.id, serverId), eq(workflowMcpServer.workspaceId, workspaceId)) + ) + .limit(1) + + if (!server) { + return createMcpErrorResponse(new Error('Server not found'), 'Server not found', 404) + } + + const [deletedTool] = await db + .delete(workflowMcpTool) + .where(and(eq(workflowMcpTool.id, toolId), eq(workflowMcpTool.serverId, serverId))) + .returning() + + if (!deletedTool) { + return createMcpErrorResponse(new Error('Tool not found'), 'Tool not found', 404) + } + + logger.info(`[${requestId}] Successfully deleted tool ${toolId}`) + + return createMcpSuccessResponse({ message: `Tool ${toolId} deleted successfully` }) + } catch (error) { + logger.error(`[${requestId}] Error deleting tool:`, error) + return createMcpErrorResponse( + error instanceof Error ? error : new Error('Failed to delete tool'), + 'Failed to delete tool', + 500 + ) + } + } +) diff --git a/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts b/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts new file mode 100644 index 0000000000..f07cacb179 --- /dev/null +++ b/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts @@ -0,0 +1,253 @@ +import { db } from '@sim/db' +import { workflow, workflowMcpServer, workflowMcpTool } from '@sim/db/schema' +import { and, eq } from 'drizzle-orm' +import type { NextRequest } from 'next/server' +import { createLogger } from '@/lib/logs/console/logger' +import { getParsedBody, withMcpAuth } from '@/lib/mcp/middleware' +import { createMcpErrorResponse, createMcpSuccessResponse } from '@/lib/mcp/utils' +import { loadWorkflowFromNormalizedTables } from '@/lib/workflows/persistence/utils' + +const logger = createLogger('WorkflowMcpToolsAPI') + +export const dynamic = 'force-dynamic' + +interface RouteParams { + id: string +} + +/** + * Sanitize a workflow name to be a valid MCP tool name. + * Tool names should be lowercase, alphanumeric with underscores. + */ +function sanitizeToolName(name: string): string { + return name + .toLowerCase() + .replace(/[^a-z0-9\s_-]/g, '') + .replace(/[\s-]+/g, '_') + .replace(/_+/g, '_') + .replace(/^_|_$/g, '') + .substring(0, 64) || 'workflow_tool' +} + +/** + * Check if a workflow has a valid start block that can accept inputs + */ +async function hasValidStartBlock(workflowId: string): Promise { + try { + const normalizedData = await loadWorkflowFromNormalizedTables(workflowId) + if (!normalizedData?.blocks) { + return false + } + + // Look for a start block + const startBlock = Object.values(normalizedData.blocks).find((block: any) => { + const blockType = block?.type + return ( + blockType === 'starter' || + blockType === 'start' || + blockType === 'start_trigger' || + blockType === 'api' || + blockType === 'api_trigger' || + blockType === 'input_trigger' + ) + }) + + return !!startBlock + } catch (error) { + logger.warn('Error checking for start block:', error) + return false + } +} + +/** + * GET - List all tools for a workflow MCP server + */ +export const GET = withMcpAuth('read')( + async (request: NextRequest, { userId, workspaceId, requestId }, { params }) => { + try { + const { id: serverId } = await params + + logger.info(`[${requestId}] Listing tools for workflow MCP server: ${serverId}`) + + // Verify server exists and belongs to workspace + const [server] = await db + .select({ id: workflowMcpServer.id }) + .from(workflowMcpServer) + .where( + and(eq(workflowMcpServer.id, serverId), eq(workflowMcpServer.workspaceId, workspaceId)) + ) + .limit(1) + + if (!server) { + return createMcpErrorResponse(new Error('Server not found'), 'Server not found', 404) + } + + // Get tools with workflow details + const tools = await db + .select({ + id: workflowMcpTool.id, + serverId: workflowMcpTool.serverId, + workflowId: workflowMcpTool.workflowId, + toolName: workflowMcpTool.toolName, + toolDescription: workflowMcpTool.toolDescription, + parameterSchema: workflowMcpTool.parameterSchema, + isEnabled: workflowMcpTool.isEnabled, + createdAt: workflowMcpTool.createdAt, + updatedAt: workflowMcpTool.updatedAt, + workflowName: workflow.name, + workflowDescription: workflow.description, + isDeployed: workflow.isDeployed, + }) + .from(workflowMcpTool) + .leftJoin(workflow, eq(workflowMcpTool.workflowId, workflow.id)) + .where(eq(workflowMcpTool.serverId, serverId)) + + logger.info(`[${requestId}] Found ${tools.length} tools for server ${serverId}`) + + return createMcpSuccessResponse({ tools }) + } catch (error) { + logger.error(`[${requestId}] Error listing tools:`, error) + return createMcpErrorResponse( + error instanceof Error ? error : new Error('Failed to list tools'), + 'Failed to list tools', + 500 + ) + } + } +) + +/** + * POST - Add a workflow as a tool to an MCP server + */ +export const POST = withMcpAuth('write')( + async (request: NextRequest, { userId, workspaceId, requestId }, { params }) => { + try { + const { id: serverId } = await params + const body = getParsedBody(request) || (await request.json()) + + logger.info(`[${requestId}] Adding tool to workflow MCP server: ${serverId}`, { + workflowId: body.workflowId, + }) + + if (!body.workflowId) { + return createMcpErrorResponse( + new Error('Missing required field: workflowId'), + 'Missing required field', + 400 + ) + } + + // Verify server exists and belongs to workspace + const [server] = await db + .select({ id: workflowMcpServer.id }) + .from(workflowMcpServer) + .where( + and(eq(workflowMcpServer.id, serverId), eq(workflowMcpServer.workspaceId, workspaceId)) + ) + .limit(1) + + if (!server) { + return createMcpErrorResponse(new Error('Server not found'), 'Server not found', 404) + } + + // Verify workflow exists and is deployed + const [workflowRecord] = await db + .select({ + id: workflow.id, + name: workflow.name, + description: workflow.description, + isDeployed: workflow.isDeployed, + workspaceId: workflow.workspaceId, + }) + .from(workflow) + .where(eq(workflow.id, body.workflowId)) + .limit(1) + + if (!workflowRecord) { + return createMcpErrorResponse(new Error('Workflow not found'), 'Workflow not found', 404) + } + + // Verify workflow belongs to the same workspace + if (workflowRecord.workspaceId !== workspaceId) { + return createMcpErrorResponse( + new Error('Workflow does not belong to this workspace'), + 'Access denied', + 403 + ) + } + + if (!workflowRecord.isDeployed) { + return createMcpErrorResponse( + new Error('Workflow must be deployed before adding as a tool'), + 'Workflow not deployed', + 400 + ) + } + + // Verify workflow has a valid start block + const hasStartBlock = await hasValidStartBlock(body.workflowId) + if (!hasStartBlock) { + return createMcpErrorResponse( + new Error('Workflow must have a Start block to be used as an MCP tool'), + 'No start block found', + 400 + ) + } + + // Check if tool already exists for this workflow + const [existingTool] = await db + .select({ id: workflowMcpTool.id }) + .from(workflowMcpTool) + .where( + and( + eq(workflowMcpTool.serverId, serverId), + eq(workflowMcpTool.workflowId, body.workflowId) + ) + ) + .limit(1) + + if (existingTool) { + return createMcpErrorResponse( + new Error('This workflow is already added as a tool to this server'), + 'Tool already exists', + 409 + ) + } + + // Generate tool name and description + const toolName = body.toolName?.trim() || sanitizeToolName(workflowRecord.name) + const toolDescription = + body.toolDescription?.trim() || workflowRecord.description || `Execute ${workflowRecord.name} workflow` + + // Create the tool + const toolId = crypto.randomUUID() + const [tool] = await db + .insert(workflowMcpTool) + .values({ + id: toolId, + serverId, + workflowId: body.workflowId, + toolName, + toolDescription, + parameterSchema: body.parameterSchema || {}, + isEnabled: true, + createdAt: new Date(), + updatedAt: new Date(), + }) + .returning() + + logger.info( + `[${requestId}] Successfully added tool ${toolName} (workflow: ${body.workflowId}) to server ${serverId}` + ) + + return createMcpSuccessResponse({ tool }, 201) + } catch (error) { + logger.error(`[${requestId}] Error adding tool:`, error) + return createMcpErrorResponse( + error instanceof Error ? error : new Error('Failed to add tool'), + 'Failed to add tool', + 500 + ) + } + } +) diff --git a/apps/sim/app/api/mcp/workflow-servers/route.ts b/apps/sim/app/api/mcp/workflow-servers/route.ts new file mode 100644 index 0000000000..3735ec41f0 --- /dev/null +++ b/apps/sim/app/api/mcp/workflow-servers/route.ts @@ -0,0 +1,107 @@ +import { db } from '@sim/db' +import { workflowMcpServer, workflowMcpTool } from '@sim/db/schema' +import { and, eq, sql } from 'drizzle-orm' +import type { NextRequest } from 'next/server' +import { createLogger } from '@/lib/logs/console/logger' +import { getParsedBody, withMcpAuth } from '@/lib/mcp/middleware' +import { createMcpErrorResponse, createMcpSuccessResponse } from '@/lib/mcp/utils' + +const logger = createLogger('WorkflowMcpServersAPI') + +export const dynamic = 'force-dynamic' + +/** + * GET - List all workflow MCP servers for the workspace + */ +export const GET = withMcpAuth('read')( + async (request: NextRequest, { userId, workspaceId, requestId }) => { + try { + logger.info(`[${requestId}] Listing workflow MCP servers for workspace ${workspaceId}`) + + const servers = await db + .select({ + id: workflowMcpServer.id, + workspaceId: workflowMcpServer.workspaceId, + createdBy: workflowMcpServer.createdBy, + name: workflowMcpServer.name, + description: workflowMcpServer.description, + isPublished: workflowMcpServer.isPublished, + publishedAt: workflowMcpServer.publishedAt, + createdAt: workflowMcpServer.createdAt, + updatedAt: workflowMcpServer.updatedAt, + toolCount: sql`( + SELECT COUNT(*)::int + FROM "workflow_mcp_tool" + WHERE "workflow_mcp_tool"."server_id" = "workflow_mcp_server"."id" + )`.as('tool_count'), + }) + .from(workflowMcpServer) + .where(eq(workflowMcpServer.workspaceId, workspaceId)) + + logger.info( + `[${requestId}] Listed ${servers.length} workflow MCP servers for workspace ${workspaceId}` + ) + return createMcpSuccessResponse({ servers }) + } catch (error) { + logger.error(`[${requestId}] Error listing workflow MCP servers:`, error) + return createMcpErrorResponse( + error instanceof Error ? error : new Error('Failed to list workflow MCP servers'), + 'Failed to list workflow MCP servers', + 500 + ) + } + } +) + +/** + * POST - Create a new workflow MCP server + */ +export const POST = withMcpAuth('write')( + async (request: NextRequest, { userId, workspaceId, requestId }) => { + try { + const body = getParsedBody(request) || (await request.json()) + + logger.info(`[${requestId}] Creating workflow MCP server:`, { + name: body.name, + workspaceId, + }) + + if (!body.name) { + return createMcpErrorResponse( + new Error('Missing required field: name'), + 'Missing required field', + 400 + ) + } + + const serverId = crypto.randomUUID() + + const [server] = await db + .insert(workflowMcpServer) + .values({ + id: serverId, + workspaceId, + createdBy: userId, + name: body.name.trim(), + description: body.description?.trim() || null, + isPublished: false, + createdAt: new Date(), + updatedAt: new Date(), + }) + .returning() + + logger.info( + `[${requestId}] Successfully created workflow MCP server: ${body.name} (ID: ${serverId})` + ) + + return createMcpSuccessResponse({ server }, 201) + } catch (error) { + logger.error(`[${requestId}] Error creating workflow MCP server:`, error) + return createMcpErrorResponse( + error instanceof Error ? error : new Error('Failed to create workflow MCP server'), + 'Failed to create workflow MCP server', + 500 + ) + } + } +) diff --git a/apps/sim/app/api/workflows/[id]/deploy/route.ts b/apps/sim/app/api/workflows/[id]/deploy/route.ts index 58a291ea26..cef214f561 100644 --- a/apps/sim/app/api/workflows/[id]/deploy/route.ts +++ b/apps/sim/app/api/workflows/[id]/deploy/route.ts @@ -1,9 +1,9 @@ -import { db, workflow, workflowDeploymentVersion } from '@sim/db' +import { db, workflow, workflowDeploymentVersion, workflowMcpTool } from '@sim/db' import { and, desc, eq } from 'drizzle-orm' import type { NextRequest } from 'next/server' import { generateRequestId } from '@/lib/core/utils/request' import { createLogger } from '@/lib/logs/console/logger' -import { deployWorkflow } from '@/lib/workflows/persistence/utils' +import { deployWorkflow, loadWorkflowFromNormalizedTables } from '@/lib/workflows/persistence/utils' import { validateWorkflowPermissions } from '@/lib/workflows/utils' import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils' @@ -12,6 +12,175 @@ const logger = createLogger('WorkflowDeployAPI') export const dynamic = 'force-dynamic' export const runtime = 'nodejs' +/** + * Extract input format from workflow blocks and generate MCP tool parameter schema + */ +async function generateMcpToolSchema(workflowId: string): Promise> { + try { + const normalizedData = await loadWorkflowFromNormalizedTables(workflowId) + if (!normalizedData?.blocks) { + return { type: 'object', properties: {} } + } + + // Find the start block + const startBlock = Object.values(normalizedData.blocks).find((block: any) => { + const blockType = block?.type + return ( + blockType === 'starter' || + blockType === 'start' || + blockType === 'start_trigger' || + blockType === 'api' || + blockType === 'api_trigger' || + blockType === 'input_trigger' + ) + }) as any + + if (!startBlock?.subBlocks?.inputFormat?.value) { + return { type: 'object', properties: {} } + } + + const inputFormat = startBlock.subBlocks.inputFormat.value + if (!Array.isArray(inputFormat) || inputFormat.length === 0) { + return { type: 'object', properties: {} } + } + + const properties: Record = {} + const required: string[] = [] + + for (const field of inputFormat) { + if (!field?.name || typeof field.name !== 'string' || !field.name.trim()) continue + + const fieldName = field.name.trim() + let jsonType = 'string' + switch (field.type) { + case 'number': + jsonType = 'number' + break + case 'boolean': + jsonType = 'boolean' + break + case 'object': + jsonType = 'object' + break + case 'array': + case 'files': + jsonType = 'array' + break + default: + jsonType = 'string' + } + + properties[fieldName] = { + type: jsonType, + description: fieldName, + } + required.push(fieldName) + } + + return { + type: 'object', + properties, + required: required.length > 0 ? required : undefined, + } + } catch (error) { + logger.warn('Error generating MCP tool schema:', error) + return { type: 'object', properties: {} } + } +} + +/** + * Check if a workflow has a valid start block + */ +async function hasValidStartBlock(workflowId: string): Promise { + try { + const normalizedData = await loadWorkflowFromNormalizedTables(workflowId) + if (!normalizedData?.blocks) { + return false + } + + const startBlock = Object.values(normalizedData.blocks).find((block: any) => { + const blockType = block?.type + return ( + blockType === 'starter' || + blockType === 'start' || + blockType === 'start_trigger' || + blockType === 'api' || + blockType === 'api_trigger' || + blockType === 'input_trigger' + ) + }) + + return !!startBlock + } catch (error) { + logger.warn('Error checking for start block:', error) + return false + } +} + +/** + * Update all MCP tools that reference this workflow with the latest parameter schema. + * If the workflow no longer has a start block, remove all MCP tools. + */ +async function syncMcpToolsOnDeploy(workflowId: string, requestId: string): Promise { + try { + // Get all MCP tools that use this workflow + const tools = await db + .select({ id: workflowMcpTool.id }) + .from(workflowMcpTool) + .where(eq(workflowMcpTool.workflowId, workflowId)) + + if (tools.length === 0) { + logger.debug(`[${requestId}] No MCP tools to sync for workflow: ${workflowId}`) + return + } + + // Check if workflow still has a valid start block + const hasStart = await hasValidStartBlock(workflowId) + if (!hasStart) { + // No start block - remove all MCP tools for this workflow + await db + .delete(workflowMcpTool) + .where(eq(workflowMcpTool.workflowId, workflowId)) + + logger.info(`[${requestId}] Removed ${tools.length} MCP tool(s) - workflow no longer has a start block: ${workflowId}`) + return + } + + // Generate the latest parameter schema + const parameterSchema = await generateMcpToolSchema(workflowId) + + // Update all tools with the new schema + await db + .update(workflowMcpTool) + .set({ + parameterSchema, + updatedAt: new Date(), + }) + .where(eq(workflowMcpTool.workflowId, workflowId)) + + logger.info(`[${requestId}] Synced ${tools.length} MCP tool(s) for workflow: ${workflowId}`) + } catch (error) { + logger.error(`[${requestId}] Error syncing MCP tools:`, error) + // Don't throw - this is a non-critical operation + } +} + +/** + * Remove all MCP tools that reference this workflow when undeploying + */ +async function removeMcpToolsOnUndeploy(workflowId: string, requestId: string): Promise { + try { + const result = await db + .delete(workflowMcpTool) + .where(eq(workflowMcpTool.workflowId, workflowId)) + + logger.info(`[${requestId}] Removed MCP tools for undeployed workflow: ${workflowId}`) + } catch (error) { + logger.error(`[${requestId}] Error removing MCP tools:`, error) + // Don't throw - this is a non-critical operation + } +} + export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) { const requestId = generateRequestId() const { id } = await params @@ -119,6 +288,9 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{ logger.info(`[${requestId}] Workflow deployed successfully: ${id}`) + // Sync MCP tools with the latest parameter schema + await syncMcpToolsOnDeploy(id, requestId) + const responseApiKeyInfo = workflowData!.workspaceId ? 'Workspace API keys' : 'Personal API keys' @@ -167,6 +339,9 @@ export async function DELETE( .where(eq(workflow.id, id)) }) + // Remove all MCP tools that reference this workflow + await removeMcpToolsOnUndeploy(id, requestId) + logger.info(`[${requestId}] Workflow undeployed successfully: ${id}`) // Track workflow undeployment diff --git a/apps/sim/app/api/workflows/[id]/deployments/[version]/activate/route.ts b/apps/sim/app/api/workflows/[id]/deployments/[version]/activate/route.ts index 4961ec65d0..6ab51a4587 100644 --- a/apps/sim/app/api/workflows/[id]/deployments/[version]/activate/route.ts +++ b/apps/sim/app/api/workflows/[id]/deployments/[version]/activate/route.ts @@ -1,4 +1,4 @@ -import { db, workflow, workflowDeploymentVersion } from '@sim/db' +import { db, workflow, workflowDeploymentVersion, workflowMcpTool } from '@sim/db' import { and, eq } from 'drizzle-orm' import type { NextRequest } from 'next/server' import { generateRequestId } from '@/lib/core/utils/request' @@ -11,6 +11,155 @@ const logger = createLogger('WorkflowActivateDeploymentAPI') export const dynamic = 'force-dynamic' export const runtime = 'nodejs' +/** + * Extract input format from a deployment version state and generate MCP tool parameter schema + */ +function generateMcpToolSchemaFromState(state: any): Record { + try { + if (!state?.blocks) { + return { type: 'object', properties: {} } + } + + // Find the start block in the deployed state + const startBlock = Object.values(state.blocks).find((block: any) => { + const blockType = block?.type + return ( + blockType === 'starter' || + blockType === 'start' || + blockType === 'start_trigger' || + blockType === 'api' || + blockType === 'api_trigger' || + blockType === 'input_trigger' + ) + }) as any + + if (!startBlock?.subBlocks?.inputFormat?.value) { + return { type: 'object', properties: {} } + } + + const inputFormat = startBlock.subBlocks.inputFormat.value + if (!Array.isArray(inputFormat) || inputFormat.length === 0) { + return { type: 'object', properties: {} } + } + + const properties: Record = {} + const required: string[] = [] + + for (const field of inputFormat) { + if (!field?.name || typeof field.name !== 'string' || !field.name.trim()) continue + + const fieldName = field.name.trim() + let jsonType = 'string' + switch (field.type) { + case 'number': + jsonType = 'number' + break + case 'boolean': + jsonType = 'boolean' + break + case 'object': + jsonType = 'object' + break + case 'array': + case 'files': + jsonType = 'array' + break + default: + jsonType = 'string' + } + + properties[fieldName] = { + type: jsonType, + description: fieldName, + } + required.push(fieldName) + } + + return { + type: 'object', + properties, + required: required.length > 0 ? required : undefined, + } + } catch (error) { + logger.warn('Error generating MCP tool schema from state:', error) + return { type: 'object', properties: {} } + } +} + +/** + * Check if a version state has a valid start block + */ +function hasValidStartBlockInState(state: any): boolean { + if (!state?.blocks) { + return false + } + + const startBlock = Object.values(state.blocks).find((block: any) => { + const blockType = block?.type + return ( + blockType === 'starter' || + blockType === 'start' || + blockType === 'start_trigger' || + blockType === 'api' || + blockType === 'api_trigger' || + blockType === 'input_trigger' + ) + }) + + return !!startBlock +} + +/** + * Sync MCP tools when activating a deployment version. + * If the version has no start block, remove all MCP tools. + */ +async function syncMcpToolsOnVersionActivate( + workflowId: string, + versionState: any, + requestId: string +): Promise { + try { + // Get all MCP tools that use this workflow + const tools = await db + .select({ id: workflowMcpTool.id }) + .from(workflowMcpTool) + .where(eq(workflowMcpTool.workflowId, workflowId)) + + if (tools.length === 0) { + logger.debug(`[${requestId}] No MCP tools to sync for workflow: ${workflowId}`) + return + } + + // Check if the activated version has a valid start block + if (!hasValidStartBlockInState(versionState)) { + // No start block - remove all MCP tools for this workflow + await db + .delete(workflowMcpTool) + .where(eq(workflowMcpTool.workflowId, workflowId)) + + logger.info(`[${requestId}] Removed ${tools.length} MCP tool(s) - activated version has no start block: ${workflowId}`) + return + } + + // Generate the parameter schema from the activated version's state + const parameterSchema = generateMcpToolSchemaFromState(versionState) + + // Update all tools with the new schema + await db + .update(workflowMcpTool) + .set({ + parameterSchema, + updatedAt: new Date(), + }) + .where(eq(workflowMcpTool.workflowId, workflowId)) + + logger.info(`[${requestId}] Synced ${tools.length} MCP tool(s) for workflow version activation: ${workflowId}`) + } catch (error) { + logger.error(`[${requestId}] Error syncing MCP tools on version activate:`, error) + // Don't throw - this is a non-critical operation + } +} + export async function POST( request: NextRequest, { params }: { params: Promise<{ id: string; version: string }> } @@ -31,6 +180,18 @@ export async function POST( const now = new Date() + // Get the state of the version being activated for MCP tool sync + const [versionData] = await db + .select({ state: workflowDeploymentVersion.state }) + .from(workflowDeploymentVersion) + .where( + and( + eq(workflowDeploymentVersion.workflowId, id), + eq(workflowDeploymentVersion.version, versionNum) + ) + ) + .limit(1) + await db.transaction(async (tx) => { await tx .update(workflowDeploymentVersion) @@ -65,6 +226,11 @@ export async function POST( await tx.update(workflow).set(updateData).where(eq(workflow.id, id)) }) + // Sync MCP tools with the activated version's parameter schema + if (versionData?.state) { + await syncMcpToolsOnVersionActivate(id, versionData.state, requestId) + } + return createSuccessResponse({ success: true, deployedAt: now }) } catch (error: any) { logger.error(`[${requestId}] Error activating deployment for workflow: ${id}`, error) diff --git a/apps/sim/app/api/workflows/[id]/deployments/[version]/revert/route.ts b/apps/sim/app/api/workflows/[id]/deployments/[version]/revert/route.ts index a3153290ca..5874791516 100644 --- a/apps/sim/app/api/workflows/[id]/deployments/[version]/revert/route.ts +++ b/apps/sim/app/api/workflows/[id]/deployments/[version]/revert/route.ts @@ -1,4 +1,4 @@ -import { db, workflow, workflowDeploymentVersion } from '@sim/db' +import { db, workflow, workflowDeploymentVersion, workflowMcpTool } from '@sim/db' import { and, eq } from 'drizzle-orm' import type { NextRequest } from 'next/server' import { env } from '@/lib/core/config/env' @@ -13,6 +13,155 @@ const logger = createLogger('RevertToDeploymentVersionAPI') export const dynamic = 'force-dynamic' export const runtime = 'nodejs' +/** + * Extract input format from a deployment version state and generate MCP tool parameter schema + */ +function generateMcpToolSchemaFromState(state: any): Record { + try { + if (!state?.blocks) { + return { type: 'object', properties: {} } + } + + // Find the start block in the deployed state + const startBlock = Object.values(state.blocks).find((block: any) => { + const blockType = block?.type + return ( + blockType === 'starter' || + blockType === 'start' || + blockType === 'start_trigger' || + blockType === 'api' || + blockType === 'api_trigger' || + blockType === 'input_trigger' + ) + }) as any + + if (!startBlock?.subBlocks?.inputFormat?.value) { + return { type: 'object', properties: {} } + } + + const inputFormat = startBlock.subBlocks.inputFormat.value + if (!Array.isArray(inputFormat) || inputFormat.length === 0) { + return { type: 'object', properties: {} } + } + + const properties: Record = {} + const required: string[] = [] + + for (const field of inputFormat) { + if (!field?.name || typeof field.name !== 'string' || !field.name.trim()) continue + + const fieldName = field.name.trim() + let jsonType = 'string' + switch (field.type) { + case 'number': + jsonType = 'number' + break + case 'boolean': + jsonType = 'boolean' + break + case 'object': + jsonType = 'object' + break + case 'array': + case 'files': + jsonType = 'array' + break + default: + jsonType = 'string' + } + + properties[fieldName] = { + type: jsonType, + description: fieldName, + } + required.push(fieldName) + } + + return { + type: 'object', + properties, + required: required.length > 0 ? required : undefined, + } + } catch (error) { + logger.warn('Error generating MCP tool schema from state:', error) + return { type: 'object', properties: {} } + } +} + +/** + * Check if a version state has a valid start block + */ +function hasValidStartBlockInState(state: any): boolean { + if (!state?.blocks) { + return false + } + + const startBlock = Object.values(state.blocks).find((block: any) => { + const blockType = block?.type + return ( + blockType === 'starter' || + blockType === 'start' || + blockType === 'start_trigger' || + blockType === 'api' || + blockType === 'api_trigger' || + blockType === 'input_trigger' + ) + }) + + return !!startBlock +} + +/** + * Sync MCP tools when reverting to a deployment version. + * If the version has no start block, remove all MCP tools. + */ +async function syncMcpToolsOnRevert( + workflowId: string, + versionState: any, + requestId: string +): Promise { + try { + // Get all MCP tools that use this workflow + const tools = await db + .select({ id: workflowMcpTool.id }) + .from(workflowMcpTool) + .where(eq(workflowMcpTool.workflowId, workflowId)) + + if (tools.length === 0) { + logger.debug(`[${requestId}] No MCP tools to sync for workflow: ${workflowId}`) + return + } + + // Check if the reverted version has a valid start block + if (!hasValidStartBlockInState(versionState)) { + // No start block - remove all MCP tools for this workflow + await db + .delete(workflowMcpTool) + .where(eq(workflowMcpTool.workflowId, workflowId)) + + logger.info(`[${requestId}] Removed ${tools.length} MCP tool(s) - reverted version has no start block: ${workflowId}`) + return + } + + // Generate the parameter schema from the reverted version's state + const parameterSchema = generateMcpToolSchemaFromState(versionState) + + // Update all tools with the new schema + await db + .update(workflowMcpTool) + .set({ + parameterSchema, + updatedAt: new Date(), + }) + .where(eq(workflowMcpTool.workflowId, workflowId)) + + logger.info(`[${requestId}] Synced ${tools.length} MCP tool(s) for workflow revert: ${workflowId}`) + } catch (error) { + logger.error(`[${requestId}] Error syncing MCP tools on revert:`, error) + // Don't throw - this is a non-critical operation + } +} + export async function POST( request: NextRequest, { params }: { params: Promise<{ id: string; version: string }> } @@ -87,6 +236,9 @@ export async function POST( .set({ lastSynced: new Date(), updatedAt: new Date() }) .where(eq(workflow.id, id)) + // Sync MCP tools with the reverted version's parameter schema + await syncMcpToolsOnRevert(id, deployedState, requestId) + try { const socketServerUrl = env.SOCKET_SERVER_URL || 'http://localhost:3002' await fetch(`${socketServerUrl}/api/workflow-reverted`, { diff --git a/apps/sim/app/api/workflows/[id]/execute/route.ts b/apps/sim/app/api/workflows/[id]/execute/route.ts index 2b9cd8beaf..763bedbc01 100644 --- a/apps/sim/app/api/workflows/[id]/execute/route.ts +++ b/apps/sim/app/api/workflows/[id]/execute/route.ts @@ -30,7 +30,7 @@ const logger = createLogger('WorkflowExecuteAPI') const ExecuteWorkflowSchema = z.object({ selectedOutputs: z.array(z.string()).optional().default([]), - triggerType: z.enum(['api', 'webhook', 'schedule', 'manual', 'chat']).optional(), + triggerType: z.enum(['api', 'webhook', 'schedule', 'manual', 'chat', 'mcp']).optional(), stream: z.boolean().optional(), useDraftState: z.boolean().optional(), input: z.any().optional(), @@ -227,7 +227,7 @@ type AsyncExecutionParams = { workflowId: string userId: string input: any - triggerType: 'api' | 'webhook' | 'schedule' | 'manual' | 'chat' + triggerType: 'api' | 'webhook' | 'schedule' | 'manual' | 'chat' | 'mcp' } /** @@ -370,14 +370,15 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id: }) const executionId = uuidv4() - type LoggingTriggerType = 'api' | 'webhook' | 'schedule' | 'manual' | 'chat' + type LoggingTriggerType = 'api' | 'webhook' | 'schedule' | 'manual' | 'chat' | 'mcp' let loggingTriggerType: LoggingTriggerType = 'manual' if ( triggerType === 'api' || triggerType === 'chat' || triggerType === 'webhook' || triggerType === 'schedule' || - triggerType === 'manual' + triggerType === 'manual' || + triggerType === 'mcp' ) { loggingTriggerType = triggerType as LoggingTriggerType } diff --git a/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/components/notifications/notifications.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/components/notifications/notifications.tsx index a112df9e6c..12eeb2c371 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/components/notifications/notifications.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/components/notifications/notifications.tsx @@ -43,7 +43,7 @@ const PRIMARY_BUTTON_STYLES = type NotificationType = 'webhook' | 'email' | 'slack' type LogLevel = 'info' | 'error' -type TriggerType = 'api' | 'webhook' | 'schedule' | 'manual' | 'chat' +type TriggerType = 'api' | 'webhook' | 'schedule' | 'manual' | 'chat' | 'mcp' type AlertRule = | 'none' | 'consecutive_failures' @@ -84,7 +84,7 @@ interface NotificationSettingsProps { } const LOG_LEVELS: LogLevel[] = ['info', 'error'] -const TRIGGER_TYPES: TriggerType[] = ['api', 'webhook', 'schedule', 'manual', 'chat'] +const TRIGGER_TYPES: TriggerType[] = ['api', 'webhook', 'schedule', 'manual', 'chat', 'mcp'] function formatAlertConfigLabel(config: { rule: AlertRule @@ -137,7 +137,7 @@ export function NotificationSettings({ workflowIds: [] as string[], allWorkflows: true, levelFilter: ['info', 'error'] as LogLevel[], - triggerFilter: ['api', 'webhook', 'schedule', 'manual', 'chat'] as TriggerType[], + triggerFilter: ['api', 'webhook', 'schedule', 'manual', 'chat', 'mcp'] as TriggerType[], includeFinalOutput: false, includeTraceSpans: false, includeRateLimits: false, @@ -207,7 +207,7 @@ export function NotificationSettings({ workflowIds: [], allWorkflows: true, levelFilter: ['info', 'error'], - triggerFilter: ['api', 'webhook', 'schedule', 'manual', 'chat'], + triggerFilter: ['api', 'webhook', 'schedule', 'manual', 'chat', 'mcp'], includeFinalOutput: false, includeTraceSpans: false, includeRateLimits: false, diff --git a/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/logs-toolbar.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/logs-toolbar.tsx index 692849fa2d..6623304dc4 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/logs-toolbar.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/logs-toolbar.tsx @@ -21,7 +21,7 @@ import { useFolderStore } from '@/stores/folders/store' import { useFilterStore } from '@/stores/logs/filters/store' import { AutocompleteSearch } from './components/search' -const CORE_TRIGGER_TYPES = ['manual', 'api', 'schedule', 'chat', 'webhook'] as const +const CORE_TRIGGER_TYPES = ['manual', 'api', 'schedule', 'chat', 'webhook', 'mcp'] as const const TIME_RANGE_OPTIONS: ComboboxOption[] = [ { value: 'All time', label: 'All time' }, diff --git a/apps/sim/app/workspace/[workspaceId]/logs/utils.ts b/apps/sim/app/workspace/[workspaceId]/logs/utils.ts index ca7d9e951d..02a1e84336 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/utils.ts +++ b/apps/sim/app/workspace/[workspaceId]/logs/utils.ts @@ -4,7 +4,7 @@ import { Badge } from '@/components/emcn' import { getIntegrationMetadata } from '@/lib/logs/get-trigger-options' import { getBlock } from '@/blocks/registry' -const CORE_TRIGGER_TYPES = ['manual', 'api', 'schedule', 'chat', 'webhook'] as const +const CORE_TRIGGER_TYPES = ['manual', 'api', 'schedule', 'chat', 'webhook', 'mcp'] as const const RUNNING_COLOR = '#22c55e' as const const PENDING_COLOR = '#f59e0b' as const diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx new file mode 100644 index 0000000000..535de236a8 --- /dev/null +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx @@ -0,0 +1,817 @@ +'use client' + +import { useCallback, useEffect, useMemo, useState } from 'react' +import { AlertTriangle, Check, ChevronDown, ChevronRight, Plus, RefreshCw, Server, Trash2 } from 'lucide-react' +import { useParams } from 'next/navigation' +import { + Badge, + Button, + Input as EmcnInput, + Label, + Popover, + PopoverContent, + PopoverItem, + PopoverTrigger, +} from '@/components/emcn' +import { Skeleton } from '@/components/ui' +import { cn } from '@/lib/core/utils/cn' +import { createLogger } from '@/lib/logs/console/logger' +import { + useAddWorkflowMcpTool, + useDeleteWorkflowMcpTool, + useUpdateWorkflowMcpTool, + useWorkflowMcpServers, + useWorkflowMcpTools, + type WorkflowMcpServer, + type WorkflowMcpTool, +} from '@/hooks/queries/workflow-mcp-servers' +import { useSubBlockStore } from '@/stores/workflows/subblock/store' +import { useWorkflowStore } from '@/stores/workflows/workflow/store' + +const logger = createLogger('McpToolDeploy') + +interface McpToolDeployProps { + workflowId: string + workflowName: string + workflowDescription?: string | null + isDeployed: boolean + onAddedToServer?: () => void +} + +/** + * Sanitize a workflow name to be a valid MCP tool name. + */ +function sanitizeToolName(name: string): string { + return name + .toLowerCase() + .replace(/[^a-z0-9\s_-]/g, '') + .replace(/[\s-]+/g, '_') + .replace(/_+/g, '_') + .replace(/^_|_$/g, '') + .substring(0, 64) || 'workflow_tool' +} + +/** + * Extract input format from workflow blocks using SubBlockStore + * The actual input format values are stored in useSubBlockStore, not directly in the block structure + */ +function extractInputFormat(blocks: Record): Array<{ name: string; type: string }> { + // Find the starter block + for (const [blockId, block] of Object.entries(blocks)) { + if (!block || typeof block !== 'object') continue + + const blockObj = block as Record + const blockType = blockObj.type + + // Check for all possible start/trigger block types + if ( + blockType === 'starter' || + blockType === 'start' || + blockType === 'start_trigger' || // This is the unified start block type + blockType === 'api' || + blockType === 'api_trigger' || + blockType === 'input_trigger' + ) { + // Get the inputFormat value from the SubBlockStore (where the actual values are stored) + const inputFormatValue = useSubBlockStore.getState().getValue(blockId, 'inputFormat') + + if (Array.isArray(inputFormatValue) && inputFormatValue.length > 0) { + return inputFormatValue + .filter( + (field: unknown): field is { name: string; type: string } => + field !== null && + typeof field === 'object' && + 'name' in field && + typeof (field as { name: unknown }).name === 'string' && + (field as { name: string }).name.trim() !== '' + ) + .map((field) => ({ + name: field.name.trim(), + type: field.type || 'string', + })) + } + + // Fallback: try to get from block's subBlocks structure (for backwards compatibility) + const subBlocks = blockObj.subBlocks as Record | undefined + if (subBlocks?.inputFormat) { + const inputFormatSubBlock = subBlocks.inputFormat as Record + const value = inputFormatSubBlock.value + if (Array.isArray(value) && value.length > 0) { + return value + .filter( + (field: unknown): field is { name: string; type: string } => + field !== null && + typeof field === 'object' && + 'name' in field && + typeof (field as { name: unknown }).name === 'string' && + (field as { name: string }).name.trim() !== '' + ) + .map((field) => ({ + name: field.name.trim(), + type: field.type || 'string', + })) + } + } + } + } + + return [] +} + +/** + * Generate JSON Schema from input format + */ +function generateParameterSchema( + inputFormat: Array<{ name: string; type: string }> +): Record { + if (inputFormat.length === 0) { + return { + type: 'object', + properties: {}, + } + } + + const properties: Record = {} + const required: string[] = [] + + for (const field of inputFormat) { + let jsonType = 'string' + switch (field.type) { + case 'number': + jsonType = 'number' + break + case 'boolean': + jsonType = 'boolean' + break + case 'object': + jsonType = 'object' + break + case 'array': + case 'files': + jsonType = 'array' + break + default: + jsonType = 'string' + } + + properties[field.name] = { + type: jsonType, + description: field.name, + } + required.push(field.name) + } + + return { + type: 'object', + properties, + required, + } +} + +/** + * Extract parameter names from a tool's parameter schema + */ +function getToolParameterNames(schema: Record): string[] { + const properties = schema.properties as Record | undefined + if (!properties) return [] + return Object.keys(properties) +} + +/** + * Check if the tool's parameters differ from the current workflow's input format + */ +function hasParameterMismatch( + tool: WorkflowMcpTool, + currentInputFormat: Array<{ name: string; type: string }> +): boolean { + const toolParams = getToolParameterNames(tool.parameterSchema as Record) + const currentParams = currentInputFormat.map((f) => f.name) + + if (toolParams.length !== currentParams.length) return true + + const toolParamSet = new Set(toolParams) + for (const param of currentParams) { + if (!toolParamSet.has(param)) return true + } + + return false +} + +/** + * Component to query tools for a single server and report back via callback. + * This pattern avoids calling hooks in a loop. + */ +function ServerToolsQuery({ + workspaceId, + server, + workflowId, + onData, +}: { + workspaceId: string + server: WorkflowMcpServer + workflowId: string + onData: (serverId: string, tool: WorkflowMcpTool | null, isLoading: boolean) => void +}) { + const { data: tools, isLoading } = useWorkflowMcpTools(workspaceId, server.id) + + useEffect(() => { + const tool = tools?.find((t) => t.workflowId === workflowId) || null + onData(server.id, tool, isLoading) + }, [tools, isLoading, workflowId, server.id, onData]) + + return null // This component doesn't render anything +} + +interface ToolOnServerProps { + server: WorkflowMcpServer + tool: WorkflowMcpTool + workspaceId: string + currentInputFormat: Array<{ name: string; type: string }> + currentParameterSchema: Record + workflowDescription: string | null | undefined + onRemoved: () => void + onUpdated: () => void +} + +function ToolOnServer({ + server, + tool, + workspaceId, + currentInputFormat, + currentParameterSchema, + workflowDescription, + onRemoved, + onUpdated, +}: ToolOnServerProps) { + const deleteToolMutation = useDeleteWorkflowMcpTool() + const updateToolMutation = useUpdateWorkflowMcpTool() + const [showConfirm, setShowConfirm] = useState(false) + const [showDetails, setShowDetails] = useState(false) + + const needsUpdate = hasParameterMismatch(tool, currentInputFormat) + const toolParams = getToolParameterNames(tool.parameterSchema as Record) + + const handleRemove = async () => { + try { + await deleteToolMutation.mutateAsync({ + workspaceId, + serverId: server.id, + toolId: tool.id, + }) + onRemoved() + } catch (error) { + logger.error('Failed to remove tool:', error) + } + } + + const handleUpdate = async () => { + try { + await updateToolMutation.mutateAsync({ + workspaceId, + serverId: server.id, + toolId: tool.id, + toolDescription: workflowDescription || `Execute workflow`, + parameterSchema: currentParameterSchema, + }) + onUpdated() + logger.info(`Updated tool ${tool.id} with new parameters`) + } catch (error) { + logger.error('Failed to update tool:', error) + } + } + + if (showConfirm) { + return ( +
+ Remove from {server.name}? +
+ + +
+
+ ) + } + + return ( +
+
setShowDetails(!showDetails)} + > +
+ {showDetails ? ( + + ) : ( + + )} + {server.name} + {server.isPublished && ( + + Published + + )} + {needsUpdate && ( + + + Needs Update + + )} +
+
e.stopPropagation()}> + {needsUpdate && ( + + )} + +
+
+ + {showDetails && ( +
+
+
+ Tool Name + {tool.toolName} +
+
+ Description + + {tool.toolDescription || '—'} + +
+
+ + Parameters ({toolParams.length}) + +
+ {toolParams.length === 0 ? ( + None + ) : ( + toolParams.map((param) => ( + + {param} + + )) + )} +
+
+
+
+ )} +
+ ) +} + +export function McpToolDeploy({ + workflowId, + workflowName, + workflowDescription, + isDeployed, + onAddedToServer, +}: McpToolDeployProps) { + const params = useParams() + const workspaceId = params.workspaceId as string + + const { data: servers = [], isLoading: isLoadingServers, refetch: refetchServers } = useWorkflowMcpServers(workspaceId) + const addToolMutation = useAddWorkflowMcpTool() + + // Get workflow blocks + const blocks = useWorkflowStore((state) => state.blocks) + + // Find the starter block ID to subscribe to its inputFormat changes + const starterBlockId = useMemo(() => { + for (const [blockId, block] of Object.entries(blocks)) { + if (!block || typeof block !== 'object') continue + const blockType = (block as { type?: string }).type + // Check for all possible start/trigger block types + if ( + blockType === 'starter' || + blockType === 'start' || + blockType === 'start_trigger' || // This is the unified start block type + blockType === 'api' || + blockType === 'api_trigger' || + blockType === 'input_trigger' + ) { + return blockId + } + } + return null + }, [blocks]) + + // Subscribe to the inputFormat value in SubBlockStore for reactivity + // Use workflowId prop directly (not activeWorkflowId from registry) to ensure we get the correct workflow's data + const subBlockValues = useSubBlockStore((state) => + workflowId ? state.workflowValues[workflowId] ?? {} : {} + ) + + // Extract and normalize input format - now reactive to SubBlockStore changes + const inputFormat = useMemo(() => { + // First try to get from SubBlockStore (where runtime values are stored) + if (starterBlockId && subBlockValues[starterBlockId]) { + const inputFormatValue = subBlockValues[starterBlockId].inputFormat + + if (Array.isArray(inputFormatValue) && inputFormatValue.length > 0) { + const filtered = inputFormatValue + .filter( + (field: unknown): field is { name: string; type: string } => + field !== null && + typeof field === 'object' && + 'name' in field && + typeof (field as { name: unknown }).name === 'string' && + (field as { name: string }).name.trim() !== '' + ) + .map((field) => ({ + name: field.name.trim(), + type: field.type || 'string', + })) + if (filtered.length > 0) { + return filtered + } + } + } + + // Fallback: try to get from block structure (for initial load or backwards compatibility) + if (starterBlockId && blocks[starterBlockId]) { + const startBlock = blocks[starterBlockId] + const subBlocksValue = startBlock?.subBlocks?.inputFormat?.value as unknown + + if (Array.isArray(subBlocksValue) && subBlocksValue.length > 0) { + const validFields: Array<{ name: string; type: string }> = [] + for (const field of subBlocksValue) { + if ( + field !== null && + typeof field === 'object' && + 'name' in field && + typeof field.name === 'string' && + field.name.trim() !== '' + ) { + validFields.push({ + name: field.name.trim(), + type: typeof field.type === 'string' ? field.type : 'string', + }) + } + } + if (validFields.length > 0) { + return validFields + } + } + } + + // Last fallback: use extractInputFormat helper + return extractInputFormat(blocks) + }, [starterBlockId, subBlockValues, blocks]) + + const parameterSchema = useMemo(() => generateParameterSchema(inputFormat), [inputFormat]) + + const [selectedServer, setSelectedServer] = useState(null) + const [toolName, setToolName] = useState('') + const [toolDescription, setToolDescription] = useState('') + const [showServerSelector, setShowServerSelector] = useState(false) + const [showParameterSchema, setShowParameterSchema] = useState(false) + + // Track tools data from each server using state instead of hooks in a loop + const [serverToolsMap, setServerToolsMap] = useState>({}) + + // Stable callback to handle tool data from ServerToolsQuery components + const handleServerToolData = useCallback((serverId: string, tool: WorkflowMcpTool | null, isLoading: boolean) => { + setServerToolsMap((prev) => { + // Only update if data has changed to prevent infinite loops + const existing = prev[serverId] + if (existing?.tool?.id === tool?.id && existing?.isLoading === isLoading) { + return prev + } + return { + ...prev, + [serverId]: { tool, isLoading }, + } + }) + }, []) + + // Find which servers already have this workflow as a tool and get the tool info + const serversWithThisWorkflow = useMemo(() => { + const result: Array<{ server: WorkflowMcpServer; tool: WorkflowMcpTool }> = [] + for (const server of servers) { + const toolInfo = serverToolsMap[server.id] + if (toolInfo?.tool) { + result.push({ server, tool: toolInfo.tool }) + } + } + return result + }, [servers, serverToolsMap]) + + // Check if any tools need updating + const toolsNeedingUpdate = useMemo(() => { + return serversWithThisWorkflow.filter(({ tool }) => hasParameterMismatch(tool, inputFormat)) + }, [serversWithThisWorkflow, inputFormat]) + + // Reset form when selected server changes + useEffect(() => { + if (selectedServer) { + setToolName(sanitizeToolName(workflowName)) + setToolDescription(workflowDescription || `Execute ${workflowName} workflow`) + } + }, [selectedServer, workflowName, workflowDescription]) + + const handleAddTool = useCallback(async () => { + if (!selectedServer || !toolName.trim()) return + + try { + await addToolMutation.mutateAsync({ + workspaceId, + serverId: selectedServer.id, + workflowId, + toolName: toolName.trim(), + toolDescription: toolDescription.trim() || undefined, + parameterSchema, + }) + + setSelectedServer(null) + setToolName('') + setToolDescription('') + + // Refetch servers to update tool count + refetchServers() + onAddedToServer?.() + + logger.info(`Added workflow ${workflowId} as tool to server ${selectedServer.id}`) + } catch (error) { + logger.error('Failed to add tool:', error) + } + }, [ + selectedServer, + toolName, + toolDescription, + workspaceId, + workflowId, + parameterSchema, + addToolMutation, + refetchServers, + onAddedToServer, + ]) + + const handleToolChanged = useCallback(() => { + // Clear the tools map to force re-query when ServerToolsQuery components re-render + setServerToolsMap({}) + refetchServers() + }, [refetchServers]) + + const availableServers = useMemo(() => { + const addedServerIds = new Set(serversWithThisWorkflow.map((s) => s.server.id)) + return servers.filter((server) => !addedServerIds.has(server.id)) + }, [servers, serversWithThisWorkflow]) + + if (!isDeployed) { + return ( +
+ +
+

Deploy workflow first

+

+ You need to deploy your workflow before adding it as an MCP tool. +

+
+
+ ) + } + + if (isLoadingServers) { + return ( +
+ + +
+ ) + } + + if (servers.length === 0) { + return ( +
+ +
+

No MCP servers yet

+

+ Create a Workflow MCP Server in Settings → Workflow MCP Servers first. +

+
+
+ ) + } + + return ( +
+ {/* Query tools for each server using separate components to follow Rules of Hooks */} + {servers.map((server) => ( + + ))} + +
+

+ Add this workflow as an MCP tool to make it callable by external MCP clients like Cursor or Claude Desktop. +

+
+ + {/* Update Warning */} + {toolsNeedingUpdate.length > 0 && ( +
+ +

+ {toolsNeedingUpdate.length} server{toolsNeedingUpdate.length > 1 ? 's have' : ' has'} outdated tool + definitions. Click "Update" on each to sync with current parameters. +

+
+ )} + + {/* Parameter Schema Preview */} +
+ + + {showParameterSchema && ( +
+ {inputFormat.length === 0 ? ( +

+ No parameters defined. Add input fields in the Starter block to define tool parameters. +

+ ) : ( +
+ {inputFormat.map((field, index) => ( +
+ + {field.name} + + + {field.type} + +
+ ))} +
+ )} +
+ )} +
+ + {/* Servers with this workflow */} + {serversWithThisWorkflow.length > 0 && ( +
+ +
+ {serversWithThisWorkflow.map(({ server, tool }) => ( + + ))} +
+
+ )} + + {/* Add to new server */} + {availableServers.length > 0 ? ( + <> +
+ + + + + + + {availableServers.map((server) => ( + { + setSelectedServer(server) + setShowServerSelector(false) + }} + > + + {server.name} + {server.isPublished && ( + + Published + + )} + + ))} + + +
+ + {selectedServer && ( + <> +
+ + setToolName(e.target.value)} + placeholder='e.g., book_flight' + className='h-[36px]' + /> +

+ Use lowercase letters, numbers, and underscores only. +

+
+ +
+ + setToolDescription(e.target.value)} + placeholder='Describe what this tool does...' + className='h-[36px]' + /> +
+ + + + {addToolMutation.isError && ( +

+ {addToolMutation.error?.message || 'Failed to add tool'} +

+ )} + + )} + + ) : serversWithThisWorkflow.length > 0 ? ( +

+ This workflow has been added to all available servers. +

+ ) : null} +
+ ) +} diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/deploy-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/deploy-modal.tsx index 84b3996fbb..dc56f77703 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/deploy-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/deploy-modal.tsx @@ -24,6 +24,7 @@ import type { WorkflowState } from '@/stores/workflows/workflow/types' import { ApiDeploy } from './components/api/api' import { ChatDeploy, type ExistingChat } from './components/chat/chat' import { GeneralDeploy } from './components/general/general' +import { McpToolDeploy } from './components/mcp-tool/mcp-tool' import { TemplateDeploy } from './components/template/template' const logger = createLogger('DeployModal') @@ -49,7 +50,7 @@ interface WorkflowDeploymentInfo { needsRedeployment: boolean } -type TabView = 'general' | 'api' | 'chat' | 'template' +type TabView = 'general' | 'api' | 'chat' | 'template' | 'mcp-tool' export function DeployModal({ open, @@ -552,6 +553,7 @@ export function DeployModal({ API Chat Template + MCP Tool @@ -610,6 +612,17 @@ export function DeployModal({ /> )} + + + {workflowId && ( + + )} + diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/index.ts b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/index.ts index 160ef9507d..52c83e392a 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/index.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/index.ts @@ -9,3 +9,4 @@ export { MCP } from './mcp/mcp' export { SSO } from './sso/sso' export { Subscription } from './subscription/subscription' export { TeamManagement } from './team-management/team-management' +export { WorkflowMcpServers } from './workflow-mcp-servers/workflow-mcp-servers' diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/workflow-mcp-servers/workflow-mcp-servers.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/workflow-mcp-servers/workflow-mcp-servers.tsx new file mode 100644 index 0000000000..bff7f32bd9 --- /dev/null +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/workflow-mcp-servers/workflow-mcp-servers.tsx @@ -0,0 +1,576 @@ +'use client' + +import { useCallback, useMemo, useState } from 'react' +import { Check, ChevronLeft, Clipboard, Globe, Plus, Search, Server, Trash2 } from 'lucide-react' +import { useParams } from 'next/navigation' +import { + Badge, + Button, + Input as EmcnInput, + Modal, + ModalBody, + ModalContent, + ModalFooter, + ModalHeader, +} from '@/components/emcn' +import { Input, Skeleton } from '@/components/ui' +import { cn } from '@/lib/core/utils/cn' +import { getBaseUrl } from '@/lib/core/utils/urls' +import { createLogger } from '@/lib/logs/console/logger' +import { + useCreateWorkflowMcpServer, + useDeleteWorkflowMcpServer, + useDeleteWorkflowMcpTool, + usePublishWorkflowMcpServer, + useUnpublishWorkflowMcpServer, + useWorkflowMcpServer, + useWorkflowMcpServers, + type WorkflowMcpServer, + type WorkflowMcpTool, +} from '@/hooks/queries/workflow-mcp-servers' + +const logger = createLogger('WorkflowMcpServers') + +function ServerSkeleton() { + return ( +
+
+ + +
+ +
+ ) +} + +interface ServerListItemProps { + server: WorkflowMcpServer + onViewDetails: () => void + onDelete: () => void + isDeleting: boolean +} + +function ServerListItem({ server, onViewDetails, onDelete, isDeleting }: ServerListItemProps) { + return ( +
e.key === 'Enter' && onViewDetails()} + > +
+ +
+
+ + {server.name} + + {server.isPublished && ( + + + Published + + )} +
+ + {server.toolCount || 0} tool{(server.toolCount || 0) !== 1 ? 's' : ''} + +
+
+ +
+ ) +} + +interface ServerDetailViewProps { + workspaceId: string + serverId: string + onBack: () => void +} + +function ServerDetailView({ workspaceId, serverId, onBack }: ServerDetailViewProps) { + const { data, isLoading, error } = useWorkflowMcpServer(workspaceId, serverId) + const publishMutation = usePublishWorkflowMcpServer() + const unpublishMutation = useUnpublishWorkflowMcpServer() + const deleteToolMutation = useDeleteWorkflowMcpTool() + const [copiedUrl, setCopiedUrl] = useState(false) + const [toolToDelete, setToolToDelete] = useState(null) + + const mcpServerUrl = useMemo(() => { + if (!data?.server?.isPublished) return null + return `${getBaseUrl()}/api/mcp/serve/${serverId}/sse` + }, [data?.server?.isPublished, serverId]) + + const handlePublish = async () => { + try { + await publishMutation.mutateAsync({ workspaceId, serverId }) + } catch (error) { + logger.error('Failed to publish server:', error) + } + } + + const handleUnpublish = async () => { + try { + await unpublishMutation.mutateAsync({ workspaceId, serverId }) + } catch (error) { + logger.error('Failed to unpublish server:', error) + } + } + + const handleCopyUrl = () => { + if (mcpServerUrl) { + navigator.clipboard.writeText(mcpServerUrl) + setCopiedUrl(true) + setTimeout(() => setCopiedUrl(false), 2000) + } + } + + const handleDeleteTool = async () => { + if (!toolToDelete) return + try { + await deleteToolMutation.mutateAsync({ + workspaceId, + serverId, + toolId: toolToDelete.id, + }) + setToolToDelete(null) + } catch (error) { + logger.error('Failed to delete tool:', error) + } + } + + if (isLoading) { + return ( +
+ + + +
+ ) + } + + if (error || !data) { + return ( +
+

Failed to load server details

+ +
+ ) + } + + const { server, tools } = data + + return ( + <> +
+
+
+
+ Server Name +

{server.name}

+
+ + {server.description && ( +
+ + Description + +

{server.description}

+
+ )} + +
+ Status +
+ {server.isPublished ? ( + <> + + + Published + + + + ) : ( + <> + Not Published + + + )} +
+ {publishMutation.isError && ( +

+ {publishMutation.error?.message || 'Failed to publish'} +

+ )} +
+ + {mcpServerUrl && ( +
+ + MCP Server URL + +
+ + {mcpServerUrl} + + +
+

+ Use this URL to connect external MCP clients like Cursor or Claude Desktop. +

+
+ )} + +
+ + Tools ({tools.length}) + + {tools.length === 0 ? ( +

+ No tools added yet. Deploy a workflow and add it as a tool from the deploy modal. +

+ ) : ( +
+ {tools.map((tool) => ( +
+
+

+ {tool.toolName} +

+ {tool.toolDescription && ( +

+ {tool.toolDescription} +

+ )} + {tool.workflowName && ( +

+ Workflow: {tool.workflowName} +

+ )} +
+ +
+ ))} +
+ )} +
+
+
+ +
+ +
+
+ + !open && setToolToDelete(null)}> + + Remove Tool + +

+ Are you sure you want to remove{' '} + {toolToDelete?.toolName}{' '} + from this server? +

+
+ + + + +
+
+ + ) +} + +/** + * Workflow MCP Servers settings component. + * Allows users to create and manage MCP servers that expose workflows as tools. + */ +export function WorkflowMcpServers() { + const params = useParams() + const workspaceId = params.workspaceId as string + + const { data: servers = [], isLoading, error } = useWorkflowMcpServers(workspaceId) + const createServerMutation = useCreateWorkflowMcpServer() + const deleteServerMutation = useDeleteWorkflowMcpServer() + + const [searchTerm, setSearchTerm] = useState('') + const [showAddForm, setShowAddForm] = useState(false) + const [formData, setFormData] = useState({ name: '', description: '' }) + const [selectedServerId, setSelectedServerId] = useState(null) + const [serverToDelete, setServerToDelete] = useState(null) + const [deletingServers, setDeletingServers] = useState>(new Set()) + + const filteredServers = useMemo(() => { + if (!searchTerm.trim()) return servers + const search = searchTerm.toLowerCase() + return servers.filter( + (server) => + server.name.toLowerCase().includes(search) || + server.description?.toLowerCase().includes(search) + ) + }, [servers, searchTerm]) + + const resetForm = useCallback(() => { + setFormData({ name: '', description: '' }) + setShowAddForm(false) + }, []) + + const handleCreateServer = async () => { + if (!formData.name.trim()) return + + try { + await createServerMutation.mutateAsync({ + workspaceId, + name: formData.name.trim(), + description: formData.description.trim() || undefined, + }) + resetForm() + } catch (error) { + logger.error('Failed to create server:', error) + } + } + + const handleDeleteServer = async () => { + if (!serverToDelete) return + + setDeletingServers((prev) => new Set(prev).add(serverToDelete.id)) + setServerToDelete(null) + + try { + await deleteServerMutation.mutateAsync({ + workspaceId, + serverId: serverToDelete.id, + }) + } catch (error) { + logger.error('Failed to delete server:', error) + } finally { + setDeletingServers((prev) => { + const next = new Set(prev) + next.delete(serverToDelete.id) + return next + }) + } + } + + const hasServers = servers.length > 0 + const showEmptyState = !hasServers && !showAddForm + const showNoResults = searchTerm.trim() && filteredServers.length === 0 && hasServers + const isFormValid = formData.name.trim().length > 0 + + // Show detail view if a server is selected + if (selectedServerId) { + return ( + setSelectedServerId(null)} + /> + ) + } + + return ( + <> +
+
+
+ + setSearchTerm(e.target.value)} + disabled={isLoading} + className='h-auto flex-1 border-0 bg-transparent p-0 font-base leading-none placeholder:text-[var(--text-tertiary)] focus-visible:ring-0 focus-visible:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-100' + /> +
+ +
+ + {showAddForm && ( +
+
+
+ + setFormData((prev) => ({ ...prev, name: e.target.value }))} + className='h-9' + /> +
+ +
+ + setFormData((prev) => ({ ...prev, description: e.target.value }))} + className='h-9' + /> +
+ +
+ + +
+
+
+ )} + +
+ {error ? ( +
+

+ {error instanceof Error ? error.message : 'Failed to load servers'} +

+
+ ) : isLoading ? ( +
+ + +
+ ) : showEmptyState ? ( +
+ +

+ No workflow MCP servers yet. +
+ Create one to expose your workflows as MCP tools. +

+
+ ) : ( +
+ {filteredServers.map((server) => ( + setSelectedServerId(server.id)} + onDelete={() => setServerToDelete(server)} + isDeleting={deletingServers.has(server.id)} + /> + ))} + {showNoResults && ( +
+ No servers found matching "{searchTerm}" +
+ )} +
+ )} +
+
+ + !open && setServerToDelete(null)}> + + Delete MCP Server + +

+ Are you sure you want to delete{' '} + {serverToDelete?.name}?{' '} + + This will remove all tools and cannot be undone. + +

+
+ + + + +
+
+ + ) +} diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/settings-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/settings-modal.tsx index b318006e96..fcfa9b47fe 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/settings-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/settings-modal.tsx @@ -4,7 +4,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import * as DialogPrimitive from '@radix-ui/react-dialog' import * as VisuallyHidden from '@radix-ui/react-visually-hidden' import { useQueryClient } from '@tanstack/react-query' -import { Files, LogIn, Settings, User, Users, Wrench } from 'lucide-react' +import { Files, LogIn, Server, Settings, User, Users, Wrench } from 'lucide-react' import { Card, Connections, @@ -40,6 +40,7 @@ import { SSO, Subscription, TeamManagement, + WorkflowMcpServers, } from '@/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components' import { TemplateProfile } from '@/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/template-profile/template-profile' import { generalSettingsKeys, useGeneralSettings } from '@/hooks/queries/general-settings' @@ -69,6 +70,7 @@ type SettingsSection = | 'copilot' | 'mcp' | 'custom-tools' + | 'workflow-mcp-servers' type NavigationSection = 'account' | 'subscription' | 'tools' | 'system' @@ -112,6 +114,7 @@ const allNavigationItems: NavigationItem[] = [ { id: 'integrations', label: 'Integrations', icon: Connections, section: 'tools' }, { id: 'custom-tools', label: 'Custom Tools', icon: Wrench, section: 'tools' }, { id: 'mcp', label: 'MCPs', icon: McpIcon, section: 'tools' }, + { id: 'workflow-mcp-servers', label: 'Workflow MCP Servers', icon: Server, section: 'tools' }, { id: 'environment', label: 'Environment', icon: FolderCode, section: 'system' }, { id: 'apikeys', label: 'API Keys', icon: Key, section: 'system' }, { @@ -459,6 +462,7 @@ export function SettingsModal({ open, onOpenChange }: SettingsModalProps) { {activeSection === 'copilot' && } {activeSection === 'mcp' && } {activeSection === 'custom-tools' && } + {activeSection === 'workflow-mcp-servers' && } diff --git a/apps/sim/background/workflow-execution.ts b/apps/sim/background/workflow-execution.ts index 96475787b9..41f6c2311a 100644 --- a/apps/sim/background/workflow-execution.ts +++ b/apps/sim/background/workflow-execution.ts @@ -14,7 +14,7 @@ export type WorkflowExecutionPayload = { workflowId: string userId: string input?: any - triggerType?: 'api' | 'webhook' | 'schedule' | 'manual' | 'chat' + triggerType?: 'api' | 'webhook' | 'schedule' | 'manual' | 'chat' | 'mcp' metadata?: Record } diff --git a/apps/sim/hooks/queries/notifications.ts b/apps/sim/hooks/queries/notifications.ts index 0779867ebd..51cce70668 100644 --- a/apps/sim/hooks/queries/notifications.ts +++ b/apps/sim/hooks/queries/notifications.ts @@ -18,7 +18,7 @@ export const notificationKeys = { type NotificationType = 'webhook' | 'email' | 'slack' type LogLevel = 'info' | 'error' -type TriggerType = 'api' | 'webhook' | 'schedule' | 'manual' | 'chat' +type TriggerType = 'api' | 'webhook' | 'schedule' | 'manual' | 'chat' | 'mcp' type AlertRuleType = | 'consecutive_failures' diff --git a/apps/sim/hooks/queries/workflow-mcp-servers.ts b/apps/sim/hooks/queries/workflow-mcp-servers.ts new file mode 100644 index 0000000000..18682e3349 --- /dev/null +++ b/apps/sim/hooks/queries/workflow-mcp-servers.ts @@ -0,0 +1,554 @@ +import { keepPreviousData, useMutation, useQuery, useQueryClient } from '@tanstack/react-query' +import { createLogger } from '@/lib/logs/console/logger' + +const logger = createLogger('WorkflowMcpServerQueries') + +/** + * Query key factories for Workflow MCP Server queries + */ +export const workflowMcpServerKeys = { + all: ['workflow-mcp-servers'] as const, + servers: (workspaceId: string) => [...workflowMcpServerKeys.all, 'servers', workspaceId] as const, + server: (workspaceId: string, serverId: string) => + [...workflowMcpServerKeys.servers(workspaceId), serverId] as const, + tools: (workspaceId: string, serverId: string) => + [...workflowMcpServerKeys.server(workspaceId, serverId), 'tools'] as const, +} + +/** + * Workflow MCP Server Types + */ +export interface WorkflowMcpServer { + id: string + workspaceId: string + createdBy: string + name: string + description: string | null + isPublished: boolean + publishedAt: string | null + createdAt: string + updatedAt: string + toolCount?: number +} + +export interface WorkflowMcpTool { + id: string + serverId: string + workflowId: string + toolName: string + toolDescription: string | null + parameterSchema: Record + isEnabled: boolean + createdAt: string + updatedAt: string + workflowName?: string + workflowDescription?: string | null + isDeployed?: boolean +} + +/** + * Fetch workflow MCP servers for a workspace + */ +async function fetchWorkflowMcpServers(workspaceId: string): Promise { + const response = await fetch(`/api/mcp/workflow-servers?workspaceId=${workspaceId}`) + + if (response.status === 404) { + return [] + } + + const data = await response.json() + + if (!response.ok) { + throw new Error(data.error || 'Failed to fetch workflow MCP servers') + } + + return data.data?.servers || [] +} + +/** + * Hook to fetch workflow MCP servers + */ +export function useWorkflowMcpServers(workspaceId: string) { + return useQuery({ + queryKey: workflowMcpServerKeys.servers(workspaceId), + queryFn: () => fetchWorkflowMcpServers(workspaceId), + enabled: !!workspaceId, + retry: false, + staleTime: 60 * 1000, + placeholderData: keepPreviousData, + }) +} + +/** + * Fetch a single workflow MCP server with its tools + */ +async function fetchWorkflowMcpServer( + workspaceId: string, + serverId: string +): Promise<{ server: WorkflowMcpServer; tools: WorkflowMcpTool[] }> { + const response = await fetch(`/api/mcp/workflow-servers/${serverId}?workspaceId=${workspaceId}`) + + const data = await response.json() + + if (!response.ok) { + throw new Error(data.error || 'Failed to fetch workflow MCP server') + } + + return { + server: data.data?.server, + tools: data.data?.tools || [], + } +} + +/** + * Hook to fetch a single workflow MCP server + */ +export function useWorkflowMcpServer(workspaceId: string, serverId: string | null) { + return useQuery({ + queryKey: workflowMcpServerKeys.server(workspaceId, serverId || ''), + queryFn: () => fetchWorkflowMcpServer(workspaceId, serverId!), + enabled: !!workspaceId && !!serverId, + retry: false, + staleTime: 30 * 1000, + }) +} + +/** + * Fetch tools for a workflow MCP server + */ +async function fetchWorkflowMcpTools( + workspaceId: string, + serverId: string +): Promise { + const response = await fetch( + `/api/mcp/workflow-servers/${serverId}/tools?workspaceId=${workspaceId}` + ) + + if (response.status === 404) { + return [] + } + + const data = await response.json() + + if (!response.ok) { + throw new Error(data.error || 'Failed to fetch workflow MCP tools') + } + + return data.data?.tools || [] +} + +/** + * Hook to fetch tools for a workflow MCP server + */ +export function useWorkflowMcpTools(workspaceId: string, serverId: string | null) { + return useQuery({ + queryKey: workflowMcpServerKeys.tools(workspaceId, serverId || ''), + queryFn: () => fetchWorkflowMcpTools(workspaceId, serverId!), + enabled: !!workspaceId && !!serverId, + retry: false, + staleTime: 30 * 1000, + placeholderData: keepPreviousData, + }) +} + +/** + * Create workflow MCP server mutation + */ +interface CreateWorkflowMcpServerParams { + workspaceId: string + name: string + description?: string +} + +export function useCreateWorkflowMcpServer() { + const queryClient = useQueryClient() + + return useMutation({ + mutationFn: async ({ workspaceId, name, description }: CreateWorkflowMcpServerParams) => { + const response = await fetch('/api/mcp/workflow-servers', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ workspaceId, name, description }), + }) + + const data = await response.json() + + if (!response.ok) { + throw new Error(data.error || 'Failed to create workflow MCP server') + } + + logger.info(`Created workflow MCP server: ${name}`) + return data.data?.server as WorkflowMcpServer + }, + onSuccess: (_data, variables) => { + queryClient.invalidateQueries({ + queryKey: workflowMcpServerKeys.servers(variables.workspaceId), + }) + }, + }) +} + +/** + * Update workflow MCP server mutation + */ +interface UpdateWorkflowMcpServerParams { + workspaceId: string + serverId: string + name?: string + description?: string +} + +export function useUpdateWorkflowMcpServer() { + const queryClient = useQueryClient() + + return useMutation({ + mutationFn: async ({ + workspaceId, + serverId, + name, + description, + }: UpdateWorkflowMcpServerParams) => { + const response = await fetch(`/api/mcp/workflow-servers/${serverId}?workspaceId=${workspaceId}`, { + method: 'PATCH', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ name, description }), + }) + + const data = await response.json() + + if (!response.ok) { + throw new Error(data.error || 'Failed to update workflow MCP server') + } + + logger.info(`Updated workflow MCP server: ${serverId}`) + return data.data?.server as WorkflowMcpServer + }, + onSuccess: (_data, variables) => { + queryClient.invalidateQueries({ + queryKey: workflowMcpServerKeys.servers(variables.workspaceId), + }) + queryClient.invalidateQueries({ + queryKey: workflowMcpServerKeys.server(variables.workspaceId, variables.serverId), + }) + }, + }) +} + +/** + * Delete workflow MCP server mutation + */ +interface DeleteWorkflowMcpServerParams { + workspaceId: string + serverId: string +} + +export function useDeleteWorkflowMcpServer() { + const queryClient = useQueryClient() + + return useMutation({ + mutationFn: async ({ workspaceId, serverId }: DeleteWorkflowMcpServerParams) => { + const response = await fetch( + `/api/mcp/workflow-servers/${serverId}?workspaceId=${workspaceId}`, + { + method: 'DELETE', + } + ) + + const data = await response.json() + + if (!response.ok) { + throw new Error(data.error || 'Failed to delete workflow MCP server') + } + + logger.info(`Deleted workflow MCP server: ${serverId}`) + return data + }, + onSuccess: (_data, variables) => { + queryClient.invalidateQueries({ + queryKey: workflowMcpServerKeys.servers(variables.workspaceId), + }) + }, + }) +} + +/** + * Publish workflow MCP server mutation + */ +interface PublishWorkflowMcpServerParams { + workspaceId: string + serverId: string +} + +export interface PublishWorkflowMcpServerResult { + server: WorkflowMcpServer + mcpServerUrl: string + message: string +} + +export function usePublishWorkflowMcpServer() { + const queryClient = useQueryClient() + + return useMutation({ + mutationFn: async ({ + workspaceId, + serverId, + }: PublishWorkflowMcpServerParams): Promise => { + const response = await fetch( + `/api/mcp/workflow-servers/${serverId}/publish?workspaceId=${workspaceId}`, + { + method: 'POST', + } + ) + + const data = await response.json() + + if (!response.ok) { + throw new Error(data.error || 'Failed to publish workflow MCP server') + } + + logger.info(`Published workflow MCP server: ${serverId}`) + return data.data + }, + onSuccess: (_data, variables) => { + queryClient.invalidateQueries({ + queryKey: workflowMcpServerKeys.servers(variables.workspaceId), + }) + queryClient.invalidateQueries({ + queryKey: workflowMcpServerKeys.server(variables.workspaceId, variables.serverId), + }) + }, + }) +} + +/** + * Unpublish workflow MCP server mutation + */ +export function useUnpublishWorkflowMcpServer() { + const queryClient = useQueryClient() + + return useMutation({ + mutationFn: async ({ workspaceId, serverId }: PublishWorkflowMcpServerParams) => { + const response = await fetch( + `/api/mcp/workflow-servers/${serverId}/publish?workspaceId=${workspaceId}`, + { + method: 'DELETE', + } + ) + + const data = await response.json() + + if (!response.ok) { + throw new Error(data.error || 'Failed to unpublish workflow MCP server') + } + + logger.info(`Unpublished workflow MCP server: ${serverId}`) + return data.data + }, + onSuccess: (_data, variables) => { + queryClient.invalidateQueries({ + queryKey: workflowMcpServerKeys.servers(variables.workspaceId), + }) + queryClient.invalidateQueries({ + queryKey: workflowMcpServerKeys.server(variables.workspaceId, variables.serverId), + }) + }, + }) +} + +/** + * Add tool to workflow MCP server mutation + */ +interface AddWorkflowMcpToolParams { + workspaceId: string + serverId: string + workflowId: string + toolName?: string + toolDescription?: string + parameterSchema?: Record +} + +export function useAddWorkflowMcpTool() { + const queryClient = useQueryClient() + + return useMutation({ + mutationFn: async ({ + workspaceId, + serverId, + workflowId, + toolName, + toolDescription, + parameterSchema, + }: AddWorkflowMcpToolParams) => { + const response = await fetch( + `/api/mcp/workflow-servers/${serverId}/tools?workspaceId=${workspaceId}`, + { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ workflowId, toolName, toolDescription, parameterSchema }), + } + ) + + const data = await response.json() + + if (!response.ok) { + throw new Error(data.error || 'Failed to add tool to workflow MCP server') + } + + logger.info(`Added tool to workflow MCP server: ${serverId}`) + return data.data?.tool as WorkflowMcpTool + }, + onSuccess: (_data, variables) => { + queryClient.invalidateQueries({ + queryKey: workflowMcpServerKeys.servers(variables.workspaceId), + }) + queryClient.invalidateQueries({ + queryKey: workflowMcpServerKeys.server(variables.workspaceId, variables.serverId), + }) + queryClient.invalidateQueries({ + queryKey: workflowMcpServerKeys.tools(variables.workspaceId, variables.serverId), + }) + }, + }) +} + +/** + * Update tool mutation + */ +interface UpdateWorkflowMcpToolParams { + workspaceId: string + serverId: string + toolId: string + toolName?: string + toolDescription?: string + parameterSchema?: Record + isEnabled?: boolean +} + +export function useUpdateWorkflowMcpTool() { + const queryClient = useQueryClient() + + return useMutation({ + mutationFn: async ({ + workspaceId, + serverId, + toolId, + ...updates + }: UpdateWorkflowMcpToolParams) => { + const response = await fetch( + `/api/mcp/workflow-servers/${serverId}/tools/${toolId}?workspaceId=${workspaceId}`, + { + method: 'PATCH', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(updates), + } + ) + + const data = await response.json() + + if (!response.ok) { + throw new Error(data.error || 'Failed to update tool') + } + + logger.info(`Updated tool ${toolId} in workflow MCP server: ${serverId}`) + return data.data?.tool as WorkflowMcpTool + }, + onSuccess: (_data, variables) => { + queryClient.invalidateQueries({ + queryKey: workflowMcpServerKeys.tools(variables.workspaceId, variables.serverId), + }) + }, + }) +} + +/** + * Delete tool mutation + */ +interface DeleteWorkflowMcpToolParams { + workspaceId: string + serverId: string + toolId: string +} + +export function useDeleteWorkflowMcpTool() { + const queryClient = useQueryClient() + + return useMutation({ + mutationFn: async ({ workspaceId, serverId, toolId }: DeleteWorkflowMcpToolParams) => { + const response = await fetch( + `/api/mcp/workflow-servers/${serverId}/tools/${toolId}?workspaceId=${workspaceId}`, + { + method: 'DELETE', + } + ) + + const data = await response.json() + + if (!response.ok) { + throw new Error(data.error || 'Failed to delete tool') + } + + logger.info(`Deleted tool ${toolId} from workflow MCP server: ${serverId}`) + return data + }, + onSuccess: (_data, variables) => { + queryClient.invalidateQueries({ + queryKey: workflowMcpServerKeys.servers(variables.workspaceId), + }) + queryClient.invalidateQueries({ + queryKey: workflowMcpServerKeys.server(variables.workspaceId, variables.serverId), + }) + queryClient.invalidateQueries({ + queryKey: workflowMcpServerKeys.tools(variables.workspaceId, variables.serverId), + }) + }, + }) +} + +/** + * Connection info for an MCP server + */ +export interface WorkflowMcpServerConnectionInfo { + serverId: string + serverName: string + sseUrl: string + httpUrl: string + authHeader: string + instructions: string +} + +/** + * Fetch connection info for a workflow MCP server + */ +async function fetchWorkflowMcpServerConnectionInfo( + workspaceId: string, + serverId: string +): Promise { + const response = await fetch( + `/api/mcp/workflow-servers/${serverId}/connection-info?workspaceId=${workspaceId}` + ) + + const data = await response.json() + + if (!response.ok) { + throw new Error(data.error || 'Failed to fetch connection info') + } + + return data.data +} + +/** + * Hook to fetch connection info for a published MCP server + */ +export function useWorkflowMcpServerConnectionInfo( + workspaceId: string, + serverId: string | null, + enabled = true +) { + return useQuery({ + queryKey: [...workflowMcpServerKeys.server(workspaceId, serverId || ''), 'connection-info'], + queryFn: () => fetchWorkflowMcpServerConnectionInfo(workspaceId, serverId!), + enabled: !!workspaceId && !!serverId && enabled, + retry: false, + staleTime: 5 * 60 * 1000, // 5 minutes - connection info doesn't change often + }) +} diff --git a/apps/sim/lib/core/rate-limiter/types.ts b/apps/sim/lib/core/rate-limiter/types.ts index a7c36f8cda..118614eb17 100644 --- a/apps/sim/lib/core/rate-limiter/types.ts +++ b/apps/sim/lib/core/rate-limiter/types.ts @@ -1,7 +1,7 @@ import { env } from '@/lib/core/config/env' import type { TokenBucketConfig } from './storage' -export type TriggerType = 'api' | 'webhook' | 'schedule' | 'manual' | 'chat' | 'api-endpoint' +export type TriggerType = 'api' | 'webhook' | 'schedule' | 'manual' | 'chat' | 'mcp' | 'api-endpoint' export type RateLimitCounterType = 'sync' | 'async' | 'api-endpoint' diff --git a/apps/sim/lib/execution/preprocessing.ts b/apps/sim/lib/execution/preprocessing.ts index c1c4fbbaee..de8bdabd5c 100644 --- a/apps/sim/lib/execution/preprocessing.ts +++ b/apps/sim/lib/execution/preprocessing.ts @@ -108,7 +108,7 @@ export interface PreprocessExecutionOptions { // Required fields workflowId: string userId: string // The authenticated user ID - triggerType: 'manual' | 'api' | 'webhook' | 'schedule' | 'chat' + triggerType: 'manual' | 'api' | 'webhook' | 'schedule' | 'chat' | 'mcp' executionId: string requestId: string diff --git a/apps/sim/lib/logs/get-trigger-options.ts b/apps/sim/lib/logs/get-trigger-options.ts index fbb7bb1d12..30a6ef4797 100644 --- a/apps/sim/lib/logs/get-trigger-options.ts +++ b/apps/sim/lib/logs/get-trigger-options.ts @@ -36,6 +36,7 @@ export function getTriggerOptions(): TriggerOption[] { { value: 'schedule', label: 'Schedule', color: '#059669' }, { value: 'chat', label: 'Chat', color: '#7c3aed' }, { value: 'webhook', label: 'Webhook', color: '#ea580c' }, + { value: 'mcp', label: 'MCP', color: '#dc2626' }, ] for (const trigger of triggers) { diff --git a/apps/sim/lib/mcp/serve-auth.ts b/apps/sim/lib/mcp/serve-auth.ts new file mode 100644 index 0000000000..791ad97a6b --- /dev/null +++ b/apps/sim/lib/mcp/serve-auth.ts @@ -0,0 +1,128 @@ +import { db } from '@sim/db' +import { workflowMcpServer } from '@sim/db/schema' +import { eq } from 'drizzle-orm' +import type { NextRequest } from 'next/server' +import { checkHybridAuth } from '@/lib/auth/hybrid' +import { createLogger } from '@/lib/logs/console/logger' +import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils' + +const logger = createLogger('McpServeAuth') + +export interface McpServeAuthResult { + success: boolean + userId?: string + workspaceId?: string + error?: string +} + +/** + * Validates authentication for accessing a workflow MCP server. + * + * Authentication can be done via: + * 1. API Key (X-API-Key header) - for programmatic access + * 2. Session cookie - for logged-in users + * + * The user must have at least read access to the workspace that owns the server. + */ +export async function validateMcpServeAuth( + request: NextRequest, + serverId: string +): Promise { + try { + // First, get the server to find its workspace + const [server] = await db + .select({ + id: workflowMcpServer.id, + workspaceId: workflowMcpServer.workspaceId, + isPublished: workflowMcpServer.isPublished, + }) + .from(workflowMcpServer) + .where(eq(workflowMcpServer.id, serverId)) + .limit(1) + + if (!server) { + return { success: false, error: 'Server not found' } + } + + if (!server.isPublished) { + return { success: false, error: 'Server is not published' } + } + + // Check authentication using hybrid auth (supports both session and API key) + const auth = await checkHybridAuth(request, { requireWorkflowId: false }) + + if (!auth.success || !auth.userId) { + return { success: false, error: auth.error || 'Authentication required' } + } + + // Verify user has access to the workspace + const permissions = await getUserEntityPermissions(auth.userId, 'workspace', server.workspaceId) + + if (!permissions) { + // For published servers, we allow access to any authenticated user + // This enables the "public but authenticated" model where anyone with a Sim account + // can use published MCP servers + logger.info( + `User ${auth.userId} accessing published MCP server ${serverId} without workspace membership` + ) + } + + return { + success: true, + userId: auth.userId, + workspaceId: server.workspaceId, + } + } catch (error) { + logger.error('Error validating MCP serve auth:', error) + return { + success: false, + error: 'Authentication validation failed', + } + } +} + +/** + * Get connection instructions for an MCP server. + * This provides the information users need to connect their MCP clients. + */ +export function getMcpServerConnectionInfo( + serverId: string, + serverName: string, + baseUrl: string +): { + sseUrl: string + httpUrl: string + authHeader: string + instructions: string +} { + const sseUrl = `${baseUrl}/api/mcp/serve/${serverId}/sse` + const httpUrl = `${baseUrl}/api/mcp/serve/${serverId}` + + return { + sseUrl, + httpUrl, + authHeader: 'X-API-Key: YOUR_SIM_API_KEY', + instructions: ` +To connect to this MCP server from Cursor or Claude Desktop: + +1. Get your Sim API key from Settings -> API Keys +2. Configure your MCP client with: + - Server URL: ${sseUrl} + - Authentication: Add header "X-API-Key" with your API key + +For Cursor, add to your MCP configuration: +{ + "mcpServers": { + "${serverName.toLowerCase().replace(/\s+/g, '-')}": { + "url": "${sseUrl}", + "headers": { + "X-API-Key": "YOUR_SIM_API_KEY" + } + } + } +} + +For Claude Desktop, configure similarly in your settings. + `.trim(), + } +} diff --git a/apps/sim/lib/mcp/workflow-tool-schema.ts b/apps/sim/lib/mcp/workflow-tool-schema.ts new file mode 100644 index 0000000000..4f20bd7d07 --- /dev/null +++ b/apps/sim/lib/mcp/workflow-tool-schema.ts @@ -0,0 +1,165 @@ +import type { InputFormatField } from '@/lib/workflows/types' + +/** + * MCP Tool Schema following the JSON Schema specification + */ +export interface McpToolInputSchema { + type: 'object' + properties: Record + required?: string[] +} + +export interface McpToolProperty { + type: string + description?: string + items?: McpToolProperty + properties?: Record +} + +export interface McpToolDefinition { + name: string + description: string + inputSchema: McpToolInputSchema +} + +/** + * Map InputFormatField type to JSON Schema type + */ +function mapFieldTypeToJsonSchemaType(fieldType: string | undefined): string { + switch (fieldType) { + case 'string': + return 'string' + case 'number': + return 'number' + case 'boolean': + return 'boolean' + case 'object': + return 'object' + case 'array': + return 'array' + case 'files': + return 'array' + default: + return 'string' + } +} + +/** + * Sanitize a workflow name to be a valid MCP tool name. + * Tool names should be lowercase, alphanumeric with underscores. + */ +export function sanitizeToolName(name: string): string { + return name + .toLowerCase() + .replace(/[^a-z0-9\s_-]/g, '') + .replace(/[\s-]+/g, '_') + .replace(/_+/g, '_') + .replace(/^_|_$/g, '') + .substring(0, 64) || 'workflow_tool' +} + +/** + * Generate MCP tool input schema from InputFormatField array. + * This converts the workflow's input format definition to JSON Schema format + * that MCP clients can use to understand tool parameters. + */ +export function generateToolInputSchema(inputFormat: InputFormatField[]): McpToolInputSchema { + const properties: Record = {} + const required: string[] = [] + + for (const field of inputFormat) { + if (!field.name) continue + + const fieldName = field.name + const fieldType = mapFieldTypeToJsonSchemaType(field.type) + + const property: McpToolProperty = { + type: fieldType, + description: fieldName, // Use field name as description by default + } + + // Handle array types + if (fieldType === 'array') { + if (field.type === 'files') { + property.items = { + type: 'object', + properties: { + name: { type: 'string', description: 'File name' }, + url: { type: 'string', description: 'File URL' }, + type: { type: 'string', description: 'MIME type' }, + size: { type: 'number', description: 'File size in bytes' }, + }, + } + property.description = 'Array of file objects' + } else { + property.items = { type: 'string' } + } + } + + properties[fieldName] = property + + // All fields are considered required by default + // (in the future, we could add an optional flag to InputFormatField) + required.push(fieldName) + } + + return { + type: 'object', + properties, + required: required.length > 0 ? required : undefined, + } +} + +/** + * Generate a complete MCP tool definition from workflow metadata and input format. + */ +export function generateToolDefinition( + workflowName: string, + workflowDescription: string | undefined | null, + inputFormat: InputFormatField[], + customToolName?: string, + customDescription?: string +): McpToolDefinition { + return { + name: customToolName || sanitizeToolName(workflowName), + description: customDescription || workflowDescription || `Execute ${workflowName} workflow`, + inputSchema: generateToolInputSchema(inputFormat), + } +} + +/** + * Extract input format from a workflow's blocks. + * Looks for the starter block and extracts its inputFormat configuration. + */ +export function extractInputFormatFromBlocks( + blocks: Record +): InputFormatField[] | null { + // Look for starter or input_trigger block + for (const [, block] of Object.entries(blocks)) { + if (!block || typeof block !== 'object') continue + + const blockObj = block as Record + const blockType = blockObj.type + + if (blockType === 'starter' || blockType === 'input_trigger') { + // Try to get inputFormat from subBlocks + const subBlocks = blockObj.subBlocks as Record | undefined + if (subBlocks?.inputFormat) { + const inputFormatSubBlock = subBlocks.inputFormat as Record + const value = inputFormatSubBlock.value + if (Array.isArray(value)) { + return value as InputFormatField[] + } + } + + // Try legacy config.params.inputFormat + const config = blockObj.config as Record | undefined + const params = config?.params as Record | undefined + if (params?.inputFormat && Array.isArray(params.inputFormat)) { + return params.inputFormat as InputFormatField[] + } + } + } + + return null +} diff --git a/apps/sim/stores/logs/filters/store.ts b/apps/sim/stores/logs/filters/store.ts index 9e0e23563a..245c6038a0 100644 --- a/apps/sim/stores/logs/filters/store.ts +++ b/apps/sim/stores/logs/filters/store.ts @@ -60,7 +60,7 @@ const parseTriggerArrayFromURL = (value: string | null): TriggerType[] => { if (!value) return [] return value .split(',') - .filter((t): t is TriggerType => ['chat', 'api', 'webhook', 'manual', 'schedule'].includes(t)) + .filter((t): t is TriggerType => ['chat', 'api', 'webhook', 'manual', 'schedule', 'mcp'].includes(t)) } const parseStringArrayFromURL = (value: string | null): string[] => { diff --git a/apps/sim/stores/logs/filters/types.ts b/apps/sim/stores/logs/filters/types.ts index 761b730f6b..249fe4b557 100644 --- a/apps/sim/stores/logs/filters/types.ts +++ b/apps/sim/stores/logs/filters/types.ts @@ -166,7 +166,7 @@ export type TimeRange = | 'Past 30 days' | 'All time' export type LogLevel = 'error' | 'info' | 'running' | 'pending' | 'all' -export type TriggerType = 'chat' | 'api' | 'webhook' | 'manual' | 'schedule' | 'all' | string +export type TriggerType = 'chat' | 'api' | 'webhook' | 'manual' | 'schedule' | 'mcp' | 'all' | string export interface FilterState { // Workspace context diff --git a/packages/db/migrations/0123_acoustic_hellcat.sql b/packages/db/migrations/0123_acoustic_hellcat.sql new file mode 100644 index 0000000000..5ede791b97 --- /dev/null +++ b/packages/db/migrations/0123_acoustic_hellcat.sql @@ -0,0 +1,34 @@ +CREATE TABLE "workflow_mcp_server" ( + "id" text PRIMARY KEY NOT NULL, + "workspace_id" text NOT NULL, + "created_by" text NOT NULL, + "name" text NOT NULL, + "description" text, + "is_published" boolean DEFAULT false NOT NULL, + "published_at" timestamp, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "workflow_mcp_tool" ( + "id" text PRIMARY KEY NOT NULL, + "server_id" text NOT NULL, + "workflow_id" text NOT NULL, + "tool_name" text NOT NULL, + "tool_description" text, + "parameter_schema" json DEFAULT '{}' NOT NULL, + "is_enabled" boolean DEFAULT true NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +ALTER TABLE "workflow_mcp_server" ADD CONSTRAINT "workflow_mcp_server_workspace_id_workspace_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspace"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "workflow_mcp_server" ADD CONSTRAINT "workflow_mcp_server_created_by_user_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "workflow_mcp_tool" ADD CONSTRAINT "workflow_mcp_tool_server_id_workflow_mcp_server_id_fk" FOREIGN KEY ("server_id") REFERENCES "public"."workflow_mcp_server"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "workflow_mcp_tool" ADD CONSTRAINT "workflow_mcp_tool_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +CREATE INDEX "workflow_mcp_server_workspace_id_idx" ON "workflow_mcp_server" USING btree ("workspace_id");--> statement-breakpoint +CREATE INDEX "workflow_mcp_server_created_by_idx" ON "workflow_mcp_server" USING btree ("created_by");--> statement-breakpoint +CREATE INDEX "workflow_mcp_server_is_published_idx" ON "workflow_mcp_server" USING btree ("is_published");--> statement-breakpoint +CREATE INDEX "workflow_mcp_tool_server_id_idx" ON "workflow_mcp_tool" USING btree ("server_id");--> statement-breakpoint +CREATE INDEX "workflow_mcp_tool_workflow_id_idx" ON "workflow_mcp_tool" USING btree ("workflow_id");--> statement-breakpoint +CREATE UNIQUE INDEX "workflow_mcp_tool_server_workflow_unique" ON "workflow_mcp_tool" USING btree ("server_id","workflow_id"); \ No newline at end of file diff --git a/packages/db/migrations/meta/0123_snapshot.json b/packages/db/migrations/meta/0123_snapshot.json index 4001416fd3..71584ca6aa 100644 --- a/packages/db/migrations/meta/0123_snapshot.json +++ b/packages/db/migrations/meta/0123_snapshot.json @@ -1,5 +1,5 @@ { - "id": "1be6ebb3-fe8a-4abd-9f4d-cfb8341f5319", + "id": "f83e4e1c-3247-4d11-9779-64587c380771", "prevId": "ec1ad797-549e-4e4e-a40b-f2a865ae4c4c", "version": "7", "dialect": "postgresql", @@ -157,8 +157,12 @@ "name": "account_user_id_user_id_fk", "tableFrom": "account", "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -249,8 +253,12 @@ "name": "api_key_user_id_user_id_fk", "tableFrom": "api_key", "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -258,8 +266,12 @@ "name": "api_key_workspace_id_workspace_id_fk", "tableFrom": "api_key", "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -267,8 +279,12 @@ "name": "api_key_created_by_user_id_fk", "tableFrom": "api_key", "tableTo": "user", - "columnsFrom": ["created_by"], - "columnsTo": ["id"], + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], "onDelete": "set null", "onUpdate": "no action" } @@ -278,7 +294,9 @@ "api_key_key_unique": { "name": "api_key_key_unique", "nullsNotDistinct": false, - "columns": ["key"] + "columns": [ + "key" + ] } }, "policies": {}, @@ -408,8 +426,12 @@ "name": "chat_workflow_id_workflow_id_fk", "tableFrom": "chat", "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -417,8 +439,12 @@ "name": "chat_user_id_user_id_fk", "tableFrom": "chat", "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -599,8 +625,12 @@ "name": "copilot_chats_user_id_user_id_fk", "tableFrom": "copilot_chats", "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -608,8 +638,12 @@ "name": "copilot_chats_workflow_id_workflow_id_fk", "tableFrom": "copilot_chats", "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -776,8 +810,12 @@ "name": "copilot_feedback_user_id_user_id_fk", "tableFrom": "copilot_feedback", "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -785,8 +823,12 @@ "name": "copilot_feedback_chat_id_copilot_chats_id_fk", "tableFrom": "copilot_feedback", "tableTo": "copilot_chats", - "columnsFrom": ["chat_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "chat_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -895,8 +937,12 @@ "name": "custom_tools_workspace_id_workspace_id_fk", "tableFrom": "custom_tools", "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -904,8 +950,12 @@ "name": "custom_tools_user_id_user_id_fk", "tableFrom": "custom_tools", "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "set null", "onUpdate": "no action" } @@ -1468,8 +1518,12 @@ "name": "document_knowledge_base_id_knowledge_base_id_fk", "tableFrom": "document", "tableTo": "knowledge_base", - "columnsFrom": ["knowledge_base_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "knowledge_base_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -1891,8 +1945,12 @@ "name": "embedding_knowledge_base_id_knowledge_base_id_fk", "tableFrom": "embedding", "tableTo": "knowledge_base", - "columnsFrom": ["knowledge_base_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "knowledge_base_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -1900,8 +1958,12 @@ "name": "embedding_document_id_document_id_fk", "tableFrom": "embedding", "tableTo": "document", - "columnsFrom": ["document_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "document_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -1953,8 +2015,12 @@ "name": "environment_user_id_user_id_fk", "tableFrom": "environment", "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -1964,7 +2030,9 @@ "environment_user_id_unique": { "name": "environment_user_id_unique", "nullsNotDistinct": false, - "columns": ["user_id"] + "columns": [ + "user_id" + ] } }, "policies": {}, @@ -2153,8 +2221,12 @@ "name": "invitation_inviter_id_user_id_fk", "tableFrom": "invitation", "tableTo": "user", - "columnsFrom": ["inviter_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "inviter_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2162,8 +2234,12 @@ "name": "invitation_organization_id_organization_id_fk", "tableFrom": "invitation", "tableTo": "organization", - "columnsFrom": ["organization_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -2330,8 +2406,12 @@ "name": "knowledge_base_user_id_user_id_fk", "tableFrom": "knowledge_base", "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2339,8 +2419,12 @@ "name": "knowledge_base_workspace_id_workspace_id_fk", "tableFrom": "knowledge_base", "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "no action", "onUpdate": "no action" } @@ -2465,8 +2549,12 @@ "name": "knowledge_base_tag_definitions_knowledge_base_id_knowledge_base_id_fk", "tableFrom": "knowledge_base_tag_definitions", "tableTo": "knowledge_base", - "columnsFrom": ["knowledge_base_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "knowledge_base_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -2570,13 +2658,6 @@ "primaryKey": false, "notNull": false }, - "status_config": { - "name": "status_config", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, "tool_count": { "name": "tool_count", "type": "integer", @@ -2673,8 +2754,12 @@ "name": "mcp_servers_workspace_id_workspace_id_fk", "tableFrom": "mcp_servers", "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2682,8 +2767,12 @@ "name": "mcp_servers_created_by_user_id_fk", "tableFrom": "mcp_servers", "tableTo": "user", - "columnsFrom": ["created_by"], - "columnsTo": ["id"], + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], "onDelete": "set null", "onUpdate": "no action" } @@ -2767,8 +2856,12 @@ "name": "member_user_id_user_id_fk", "tableFrom": "member", "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2776,8 +2869,12 @@ "name": "member_organization_id_organization_id_fk", "tableFrom": "member", "tableTo": "organization", - "columnsFrom": ["organization_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -2895,8 +2992,12 @@ "name": "memory_workflow_id_workflow_id_fk", "tableFrom": "memory", "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -3125,8 +3226,12 @@ "name": "paused_executions_workflow_id_workflow_id_fk", "tableFrom": "paused_executions", "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -3332,8 +3437,12 @@ "name": "permissions_user_id_user_id_fk", "tableFrom": "permissions", "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -3504,8 +3613,12 @@ "name": "resume_queue_paused_execution_id_paused_executions_id_fk", "tableFrom": "resume_queue", "tableTo": "paused_executions", - "columnsFrom": ["paused_execution_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "paused_execution_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -3612,8 +3725,12 @@ "name": "session_user_id_user_id_fk", "tableFrom": "session", "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -3621,8 +3738,12 @@ "name": "session_active_organization_id_organization_id_fk", "tableFrom": "session", "tableTo": "organization", - "columnsFrom": ["active_organization_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "active_organization_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "set null", "onUpdate": "no action" } @@ -3632,7 +3753,9 @@ "session_token_unique": { "name": "session_token_unique", "nullsNotDistinct": false, - "columns": ["token"] + "columns": [ + "token" + ] } }, "policies": {}, @@ -3739,8 +3862,12 @@ "name": "settings_user_id_user_id_fk", "tableFrom": "settings", "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -3750,7 +3877,9 @@ "settings_user_id_unique": { "name": "settings_user_id_unique", "nullsNotDistinct": false, - "columns": ["user_id"] + "columns": [ + "user_id" + ] } }, "policies": {}, @@ -3877,8 +4006,12 @@ "name": "sso_provider_user_id_user_id_fk", "tableFrom": "sso_provider", "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -3886,8 +4019,12 @@ "name": "sso_provider_organization_id_organization_id_fk", "tableFrom": "sso_provider", "tableTo": "organization", - "columnsFrom": ["organization_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -4143,8 +4280,12 @@ "name": "template_creators_created_by_user_id_fk", "tableFrom": "template_creators", "tableTo": "user", - "columnsFrom": ["created_by"], - "columnsTo": ["id"], + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], "onDelete": "set null", "onUpdate": "no action" } @@ -4328,8 +4469,12 @@ "name": "template_stars_user_id_user_id_fk", "tableFrom": "template_stars", "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -4337,8 +4482,12 @@ "name": "template_stars_template_id_templates_id_fk", "tableFrom": "template_stars", "tableTo": "templates", - "columnsFrom": ["template_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "template_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -4579,8 +4728,12 @@ "name": "templates_workflow_id_workflow_id_fk", "tableFrom": "templates", "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "set null", "onUpdate": "no action" }, @@ -4588,8 +4741,12 @@ "name": "templates_creator_id_template_creators_id_fk", "tableFrom": "templates", "tableTo": "template_creators", - "columnsFrom": ["creator_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "creator_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "set null", "onUpdate": "no action" } @@ -4667,7 +4824,9 @@ "user_email_unique": { "name": "user_email_unique", "nullsNotDistinct": false, - "columns": ["email"] + "columns": [ + "email" + ] } }, "policies": {}, @@ -4858,8 +5017,12 @@ "name": "user_stats_user_id_user_id_fk", "tableFrom": "user_stats", "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -4869,7 +5032,9 @@ "user_stats_user_id_unique": { "name": "user_stats_user_id_unique", "nullsNotDistinct": false, - "columns": ["user_id"] + "columns": [ + "user_id" + ] } }, "policies": {}, @@ -4986,7 +5151,9 @@ "waitlist_email_unique": { "name": "waitlist_email_unique", "nullsNotDistinct": false, - "columns": ["email"] + "columns": [ + "email" + ] } }, "policies": {}, @@ -5111,8 +5278,12 @@ "name": "webhook_workflow_id_workflow_id_fk", "tableFrom": "webhook", "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5120,8 +5291,12 @@ "name": "webhook_block_id_workflow_blocks_id_fk", "tableFrom": "webhook", "tableTo": "workflow_blocks", - "columnsFrom": ["block_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "block_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -5289,8 +5464,12 @@ "name": "workflow_user_id_user_id_fk", "tableFrom": "workflow", "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5298,8 +5477,12 @@ "name": "workflow_workspace_id_workspace_id_fk", "tableFrom": "workflow", "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5307,8 +5490,12 @@ "name": "workflow_folder_id_workflow_folder_id_fk", "tableFrom": "workflow", "tableTo": "workflow_folder", - "columnsFrom": ["folder_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "folder_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "set null", "onUpdate": "no action" } @@ -5459,8 +5646,12 @@ "name": "workflow_blocks_workflow_id_workflow_id_fk", "tableFrom": "workflow_blocks", "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -5672,8 +5863,12 @@ "name": "workflow_checkpoints_user_id_user_id_fk", "tableFrom": "workflow_checkpoints", "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5681,8 +5876,12 @@ "name": "workflow_checkpoints_workflow_id_workflow_id_fk", "tableFrom": "workflow_checkpoints", "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5690,8 +5889,12 @@ "name": "workflow_checkpoints_chat_id_copilot_chats_id_fk", "tableFrom": "workflow_checkpoints", "tableTo": "copilot_chats", - "columnsFrom": ["chat_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "chat_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -5821,8 +6024,12 @@ "name": "workflow_deployment_version_workflow_id_workflow_id_fk", "tableFrom": "workflow_deployment_version", "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -5945,8 +6152,12 @@ "name": "workflow_edges_workflow_id_workflow_id_fk", "tableFrom": "workflow_edges", "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5954,8 +6165,12 @@ "name": "workflow_edges_source_block_id_workflow_blocks_id_fk", "tableFrom": "workflow_edges", "tableTo": "workflow_blocks", - "columnsFrom": ["source_block_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "source_block_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5963,8 +6178,12 @@ "name": "workflow_edges_target_block_id_workflow_blocks_id_fk", "tableFrom": "workflow_edges", "tableTo": "workflow_blocks", - "columnsFrom": ["target_block_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "target_block_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -6199,8 +6418,12 @@ "name": "workflow_execution_logs_workflow_id_workflow_id_fk", "tableFrom": "workflow_execution_logs", "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -6208,8 +6431,12 @@ "name": "workflow_execution_logs_state_snapshot_id_workflow_execution_snapshots_id_fk", "tableFrom": "workflow_execution_logs", "tableTo": "workflow_execution_snapshots", - "columnsFrom": ["state_snapshot_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "state_snapshot_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "no action", "onUpdate": "no action" }, @@ -6217,8 +6444,12 @@ "name": "workflow_execution_logs_deployment_version_id_workflow_deployment_version_id_fk", "tableFrom": "workflow_execution_logs", "tableTo": "workflow_deployment_version", - "columnsFrom": ["deployment_version_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "deployment_version_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "set null", "onUpdate": "no action" } @@ -6338,8 +6569,12 @@ "name": "workflow_execution_snapshots_workflow_id_workflow_id_fk", "tableFrom": "workflow_execution_snapshots", "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -6484,8 +6719,12 @@ "name": "workflow_folder_user_id_user_id_fk", "tableFrom": "workflow_folder", "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -6493,8 +6732,305 @@ "name": "workflow_folder_workspace_id_workspace_id_fk", "tableFrom": "workflow_folder", "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_mcp_server": { + "name": "workflow_mcp_server", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_published": { + "name": "is_published", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "published_at": { + "name": "published_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_mcp_server_workspace_id_idx": { + "name": "workflow_mcp_server_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_mcp_server_created_by_idx": { + "name": "workflow_mcp_server_created_by_idx", + "columns": [ + { + "expression": "created_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_mcp_server_is_published_idx": { + "name": "workflow_mcp_server_is_published_idx", + "columns": [ + { + "expression": "is_published", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_mcp_server_workspace_id_workspace_id_fk": { + "name": "workflow_mcp_server_workspace_id_workspace_id_fk", + "tableFrom": "workflow_mcp_server", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_mcp_server_created_by_user_id_fk": { + "name": "workflow_mcp_server_created_by_user_id_fk", + "tableFrom": "workflow_mcp_server", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_mcp_tool": { + "name": "workflow_mcp_tool", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "server_id": { + "name": "server_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tool_name": { + "name": "tool_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tool_description": { + "name": "tool_description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "parameter_schema": { + "name": "parameter_schema", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "is_enabled": { + "name": "is_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_mcp_tool_server_id_idx": { + "name": "workflow_mcp_tool_server_id_idx", + "columns": [ + { + "expression": "server_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_mcp_tool_workflow_id_idx": { + "name": "workflow_mcp_tool_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_mcp_tool_server_workflow_unique": { + "name": "workflow_mcp_tool_server_workflow_unique", + "columns": [ + { + "expression": "server_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_mcp_tool_server_id_workflow_mcp_server_id_fk": { + "name": "workflow_mcp_tool_server_id_workflow_mcp_server_id_fk", + "tableFrom": "workflow_mcp_tool", + "tableTo": "workflow_mcp_server", + "columnsFrom": [ + "server_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_mcp_tool_workflow_id_workflow_id_fk": { + "name": "workflow_mcp_tool_workflow_id_workflow_id_fk", + "tableFrom": "workflow_mcp_tool", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -6627,8 +7163,12 @@ "name": "workflow_schedule_workflow_id_workflow_id_fk", "tableFrom": "workflow_schedule", "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -6636,8 +7176,12 @@ "name": "workflow_schedule_block_id_workflow_blocks_id_fk", "tableFrom": "workflow_schedule", "tableTo": "workflow_blocks", - "columnsFrom": ["block_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "block_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -6735,8 +7279,12 @@ "name": "workflow_subflows_workflow_id_workflow_id_fk", "tableFrom": "workflow_subflows", "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -6803,8 +7351,12 @@ "name": "workspace_owner_id_user_id_fk", "tableFrom": "workspace", "tableTo": "user", - "columnsFrom": ["owner_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "owner_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -6812,8 +7364,12 @@ "name": "workspace_billed_account_user_id_user_id_fk", "tableFrom": "workspace", "tableTo": "user", - "columnsFrom": ["billed_account_user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "billed_account_user_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "no action", "onUpdate": "no action" } @@ -6884,8 +7440,12 @@ "name": "workspace_environment_workspace_id_workspace_id_fk", "tableFrom": "workspace_environment", "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -6987,8 +7547,12 @@ "name": "workspace_file_workspace_id_workspace_id_fk", "tableFrom": "workspace_file", "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -6996,8 +7560,12 @@ "name": "workspace_file_uploaded_by_user_id_fk", "tableFrom": "workspace_file", "tableTo": "user", - "columnsFrom": ["uploaded_by"], - "columnsTo": ["id"], + "columnsFrom": [ + "uploaded_by" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -7007,7 +7575,9 @@ "workspace_file_key_unique": { "name": "workspace_file_key_unique", "nullsNotDistinct": false, - "columns": ["key"] + "columns": [ + "key" + ] } }, "policies": {}, @@ -7141,8 +7711,12 @@ "name": "workspace_files_user_id_user_id_fk", "tableFrom": "workspace_files", "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -7150,8 +7724,12 @@ "name": "workspace_files_workspace_id_workspace_id_fk", "tableFrom": "workspace_files", "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -7161,7 +7739,9 @@ "workspace_files_key_unique": { "name": "workspace_files_key_unique", "nullsNotDistinct": false, - "columns": ["key"] + "columns": [ + "key" + ] } }, "policies": {}, @@ -7258,8 +7838,12 @@ "name": "workspace_invitation_workspace_id_workspace_id_fk", "tableFrom": "workspace_invitation", "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -7267,8 +7851,12 @@ "name": "workspace_invitation_inviter_id_user_id_fk", "tableFrom": "workspace_invitation", "tableTo": "user", - "columnsFrom": ["inviter_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "inviter_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -7278,7 +7866,9 @@ "workspace_invitation_token_unique": { "name": "workspace_invitation_token_unique", "nullsNotDistinct": false, - "columns": ["token"] + "columns": [ + "token" + ] } }, "policies": {}, @@ -7440,8 +8030,12 @@ "name": "workspace_notification_delivery_subscription_id_workspace_notification_subscription_id_fk", "tableFrom": "workspace_notification_delivery", "tableTo": "workspace_notification_subscription", - "columnsFrom": ["subscription_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "subscription_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -7449,8 +8043,12 @@ "name": "workspace_notification_delivery_workflow_id_workflow_id_fk", "tableFrom": "workspace_notification_delivery", "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -7650,8 +8248,12 @@ "name": "workspace_notification_subscription_workspace_id_workspace_id_fk", "tableFrom": "workspace_notification_subscription", "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" }, @@ -7659,8 +8261,12 @@ "name": "workspace_notification_subscription_created_by_user_id_fk", "tableFrom": "workspace_notification_subscription", "tableTo": "user", - "columnsFrom": ["created_by"], - "columnsTo": ["id"], + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], "onDelete": "cascade", "onUpdate": "no action" } @@ -7676,37 +8282,65 @@ "public.billing_blocked_reason": { "name": "billing_blocked_reason", "schema": "public", - "values": ["payment_failed", "dispute"] + "values": [ + "payment_failed", + "dispute" + ] }, "public.notification_delivery_status": { "name": "notification_delivery_status", "schema": "public", - "values": ["pending", "in_progress", "success", "failed"] + "values": [ + "pending", + "in_progress", + "success", + "failed" + ] }, "public.notification_type": { "name": "notification_type", "schema": "public", - "values": ["webhook", "email", "slack"] + "values": [ + "webhook", + "email", + "slack" + ] }, "public.permission_type": { "name": "permission_type", "schema": "public", - "values": ["admin", "write", "read"] + "values": [ + "admin", + "write", + "read" + ] }, "public.template_creator_type": { "name": "template_creator_type", "schema": "public", - "values": ["user", "organization"] + "values": [ + "user", + "organization" + ] }, "public.template_status": { "name": "template_status", "schema": "public", - "values": ["pending", "approved", "rejected"] + "values": [ + "pending", + "approved", + "rejected" + ] }, "public.workspace_invitation_status": { "name": "workspace_invitation_status", "schema": "public", - "values": ["pending", "accepted", "rejected", "cancelled"] + "values": [ + "pending", + "accepted", + "rejected", + "cancelled" + ] } }, "schemas": {}, @@ -7719,4 +8353,4 @@ "schemas": {}, "tables": {} } -} +} \ No newline at end of file diff --git a/packages/db/migrations/meta/_journal.json b/packages/db/migrations/meta/_journal.json index 2a414a1580..124b3bf979 100644 --- a/packages/db/migrations/meta/_journal.json +++ b/packages/db/migrations/meta/_journal.json @@ -859,9 +859,9 @@ { "idx": 123, "version": "7", - "when": 1765932898404, - "tag": "0123_windy_lockheed", + "when": 1765929938586, + "tag": "0123_acoustic_hellcat", "breakpoints": true } ] -} +} \ No newline at end of file diff --git a/packages/db/schema.ts b/packages/db/schema.ts index 6e8cbfec38..779b8b27c3 100644 --- a/packages/db/schema.ts +++ b/packages/db/schema.ts @@ -1598,3 +1598,62 @@ export const ssoProvider = pgTable( organizationIdIdx: index('sso_provider_organization_id_idx').on(table.organizationId), }) ) + +/** + * Workflow MCP Servers - User-created MCP servers that expose workflows as tools. + * These servers can be published and accessed by external MCP clients via OAuth. + */ +export const workflowMcpServer = pgTable( + 'workflow_mcp_server', + { + id: text('id').primaryKey(), + workspaceId: text('workspace_id') + .notNull() + .references(() => workspace.id, { onDelete: 'cascade' }), + createdBy: text('created_by') + .notNull() + .references(() => user.id, { onDelete: 'cascade' }), + name: text('name').notNull(), + description: text('description'), + isPublished: boolean('is_published').notNull().default(false), + publishedAt: timestamp('published_at'), + createdAt: timestamp('created_at').notNull().defaultNow(), + updatedAt: timestamp('updated_at').notNull().defaultNow(), + }, + (table) => ({ + workspaceIdIdx: index('workflow_mcp_server_workspace_id_idx').on(table.workspaceId), + createdByIdx: index('workflow_mcp_server_created_by_idx').on(table.createdBy), + isPublishedIdx: index('workflow_mcp_server_is_published_idx').on(table.isPublished), + }) +) + +/** + * Workflow MCP Tools - Workflows registered as tools within a Workflow MCP Server. + * Each tool maps to a deployed workflow's execute endpoint. + */ +export const workflowMcpTool = pgTable( + 'workflow_mcp_tool', + { + id: text('id').primaryKey(), + serverId: text('server_id') + .notNull() + .references(() => workflowMcpServer.id, { onDelete: 'cascade' }), + workflowId: text('workflow_id') + .notNull() + .references(() => workflow.id, { onDelete: 'cascade' }), + toolName: text('tool_name').notNull(), + toolDescription: text('tool_description'), + parameterSchema: json('parameter_schema').notNull().default('{}'), + isEnabled: boolean('is_enabled').notNull().default(true), + createdAt: timestamp('created_at').notNull().defaultNow(), + updatedAt: timestamp('updated_at').notNull().defaultNow(), + }, + (table) => ({ + serverIdIdx: index('workflow_mcp_tool_server_id_idx').on(table.serverId), + workflowIdIdx: index('workflow_mcp_tool_workflow_id_idx').on(table.workflowId), + serverWorkflowUnique: uniqueIndex('workflow_mcp_tool_server_workflow_unique').on( + table.serverId, + table.workflowId + ), + }) +) From a15ac7360da79f5fd02cdcc2312086573da35c60 Mon Sep 17 00:00:00 2001 From: "priyanshu.solanki" Date: Tue, 16 Dec 2025 17:44:52 -0700 Subject: [PATCH 02/27] fixed the issue of UI rendering for deleted mcp servers --- .../components/mcp-tool/mcp-tool.tsx | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx index 535de236a8..37a9a67c3b 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx @@ -229,7 +229,7 @@ interface ToolOnServerProps { currentInputFormat: Array<{ name: string; type: string }> currentParameterSchema: Record workflowDescription: string | null | undefined - onRemoved: () => void + onRemoved: (serverId: string) => void onUpdated: () => void } @@ -258,7 +258,7 @@ function ToolOnServer({ serverId: server.id, toolId: tool.id, }) - onRemoved() + onRemoved(server.id) } catch (error) { logger.error('Failed to remove tool:', error) } @@ -576,9 +576,16 @@ export function McpToolDeploy({ onAddedToServer, ]) - const handleToolChanged = useCallback(() => { - // Clear the tools map to force re-query when ServerToolsQuery components re-render - setServerToolsMap({}) + const handleToolChanged = useCallback((removedServerId?: string) => { + // If a tool was removed from a specific server, clear just that entry + // The ServerToolsQuery component will re-query and update the map + if (removedServerId) { + setServerToolsMap((prev) => { + const next = { ...prev } + delete next[removedServerId] + return next + }) + } refetchServers() }, [refetchServers]) @@ -711,8 +718,8 @@ export function McpToolDeploy({ currentInputFormat={inputFormat} currentParameterSchema={parameterSchema} workflowDescription={workflowDescription} - onRemoved={handleToolChanged} - onUpdated={handleToolChanged} + onRemoved={(serverId) => handleToolChanged(serverId)} + onUpdated={() => handleToolChanged()} /> ))} From 57f3697dd5b0905653726e948cfbd57e97166eda Mon Sep 17 00:00:00 2001 From: "priyanshu.solanki" Date: Tue, 16 Dec 2025 17:52:10 -0700 Subject: [PATCH 03/27] fixing lint issues --- apps/sim/app/api/mcp/discover/route.ts | 29 +- .../sim/app/api/mcp/serve/[serverId]/route.ts | 50 +- .../app/api/mcp/serve/[serverId]/sse/route.ts | 23 +- .../workflow-servers/[id]/publish/route.ts | 4 +- .../api/mcp/workflow-servers/[id]/route.ts | 6 +- .../mcp/workflow-servers/[id]/tools/route.ts | 20 +- .../sim/app/api/mcp/workflow-servers/route.ts | 4 +- .../app/api/workflows/[id]/deploy/route.ts | 10 +- .../deployments/[version]/activate/route.ts | 14 +- .../deployments/[version]/revert/route.ts | 14 +- .../components/mcp-tool/mcp-tool.tsx | 144 ++-- .../workflow-mcp-servers.tsx | 27 +- .../sim/hooks/queries/workflow-mcp-servers.ts | 13 +- apps/sim/lib/core/rate-limiter/types.ts | 9 +- apps/sim/lib/mcp/workflow-tool-schema.ts | 16 +- apps/sim/stores/logs/filters/store.ts | 4 +- apps/sim/stores/logs/filters/types.ts | 10 +- .../db/migrations/meta/0123_snapshot.json | 716 +++++------------- packages/db/migrations/meta/_journal.json | 2 +- 19 files changed, 408 insertions(+), 707 deletions(-) diff --git a/apps/sim/app/api/mcp/discover/route.ts b/apps/sim/app/api/mcp/discover/route.ts index 775ebbf134..0161ed9a05 100644 --- a/apps/sim/app/api/mcp/discover/route.ts +++ b/apps/sim/app/api/mcp/discover/route.ts @@ -1,6 +1,6 @@ import { db } from '@sim/db' import { permissions, workflowMcpServer, workspace } from '@sim/db/schema' -import { eq, and, sql } from 'drizzle-orm' +import { and, eq, sql } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { checkHybridAuth } from '@/lib/auth/hybrid' import { getBaseUrl } from '@/lib/core/utils/urls' @@ -12,24 +12,24 @@ export const dynamic = 'force-dynamic' /** * GET - Discover all published MCP servers available to the authenticated user - * + * * This endpoint allows external MCP clients to discover available servers * using just their API key, without needing to know workspace IDs. - * + * * Authentication: API Key (X-API-Key header) or Session - * + * * Returns all published MCP servers from workspaces the user has access to. */ export async function GET(request: NextRequest) { try { // Authenticate the request const auth = await checkHybridAuth(request, { requireWorkflowId: false }) - + if (!auth.success || !auth.userId) { return NextResponse.json( - { - success: false, - error: 'Authentication required. Provide X-API-Key header with your Sim API key.' + { + success: false, + error: 'Authentication required. Provide X-API-Key header with your Sim API key.', }, { status: 401 } ) @@ -41,14 +41,9 @@ export async function GET(request: NextRequest) { const userWorkspacePermissions = await db .select({ entityId: permissions.entityId }) .from(permissions) - .where( - and( - eq(permissions.userId, userId), - eq(permissions.entityType, 'workspace') - ) - ) + .where(and(eq(permissions.userId, userId), eq(permissions.entityType, 'workspace'))) - const workspaceIds = userWorkspacePermissions.map(w => w.entityId) + const workspaceIds = userWorkspacePermissions.map((w) => w.entityId) if (workspaceIds.length === 0) { return NextResponse.json({ @@ -87,7 +82,7 @@ export async function GET(request: NextRequest) { const baseUrl = getBaseUrl() // Format response with connection URLs - const formattedServers = servers.map(server => ({ + const formattedServers = servers.map((server) => ({ id: server.id, name: server.name, description: server.description, @@ -119,7 +114,7 @@ export async function GET(request: NextRequest) { body: '{"jsonrpc":"2.0","id":1,"method":"tools/list"}', }, callTool: { - method: 'POST', + method: 'POST', body: '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"TOOL_NAME","arguments":{}}}', }, }, diff --git a/apps/sim/app/api/mcp/serve/[serverId]/route.ts b/apps/sim/app/api/mcp/serve/[serverId]/route.ts index e09890a39d..a89dcbbc42 100644 --- a/apps/sim/app/api/mcp/serve/[serverId]/route.ts +++ b/apps/sim/app/api/mcp/serve/[serverId]/route.ts @@ -86,10 +86,7 @@ async function validateServer(serverId: string) { /** * GET - Server info and capabilities (MCP initialize) */ -export async function GET( - request: NextRequest, - { params }: { params: Promise } -) { +export async function GET(request: NextRequest, { params }: { params: Promise }) { const { serverId } = await params try { @@ -122,10 +119,7 @@ export async function GET( /** * POST - Handle MCP JSON-RPC requests */ -export async function POST( - request: NextRequest, - { params }: { params: Promise } -) { +export async function POST(request: NextRequest, { params }: { params: Promise }) { const { serverId } = await params try { @@ -151,10 +145,9 @@ export async function POST( const rpcRequest = body as JsonRpcRequest if (rpcRequest.jsonrpc !== '2.0' || !rpcRequest.method) { - return NextResponse.json( - createJsonRpcError(rpcRequest?.id || 0, -32600, 'Invalid Request'), - { status: 400 } - ) + return NextResponse.json(createJsonRpcError(rpcRequest?.id || 0, -32600, 'Invalid Request'), { + status: 400, + }) } // Handle different MCP methods @@ -178,7 +171,9 @@ export async function POST( case 'tools/call': { // Get the API key from the request to forward to the workflow execute call - const apiKey = request.headers.get('X-API-Key') || request.headers.get('Authorization')?.replace('Bearer ', '') + const apiKey = + request.headers.get('X-API-Key') || + request.headers.get('Authorization')?.replace('Bearer ', '') return handleToolsCall(rpcRequest, serverId, auth.userId, server.workspaceId, apiKey) } @@ -193,10 +188,7 @@ export async function POST( } } catch (error) { logger.error('Error handling MCP request:', error) - return NextResponse.json( - createJsonRpcError(0, -32603, 'Internal error'), - { status: 500 } - ) + return NextResponse.json(createJsonRpcError(0, -32603, 'Internal error'), { status: 500 }) } } @@ -236,15 +228,12 @@ async function handleToolsList( }, })) - return NextResponse.json( - createJsonRpcResponse(rpcRequest.id, { tools: mcpTools }) - ) + return NextResponse.json(createJsonRpcResponse(rpcRequest.id, { tools: mcpTools })) } catch (error) { logger.error('Error listing tools:', error) - return NextResponse.json( - createJsonRpcError(rpcRequest.id, -32603, 'Failed to list tools'), - { status: 500 } - ) + return NextResponse.json(createJsonRpcError(rpcRequest.id, -32603, 'Failed to list tools'), { + status: 500, + }) } } @@ -259,7 +248,9 @@ async function handleToolsCall( apiKey?: string | null ): Promise { try { - const params = rpcRequest.params as { name: string; arguments?: Record } | undefined + const params = rpcRequest.params as + | { name: string; arguments?: Record } + | undefined if (!params?.name) { return NextResponse.json( @@ -318,7 +309,7 @@ async function handleToolsCall( const executeHeaders: Record = { 'Content-Type': 'application/json', } - + // Forward the API key for authentication if (apiKey) { executeHeaders['X-API-Key'] = apiKey @@ -362,9 +353,8 @@ async function handleToolsCall( ) } catch (error) { logger.error('Error calling tool:', error) - return NextResponse.json( - createJsonRpcError(rpcRequest.id, -32603, 'Tool execution failed'), - { status: 500 } - ) + return NextResponse.json(createJsonRpcError(rpcRequest.id, -32603, 'Tool execution failed'), { + status: 500, + }) } } diff --git a/apps/sim/app/api/mcp/serve/[serverId]/sse/route.ts b/apps/sim/app/api/mcp/serve/[serverId]/sse/route.ts index 0fddff9cbc..bf20ac2e94 100644 --- a/apps/sim/app/api/mcp/serve/[serverId]/sse/route.ts +++ b/apps/sim/app/api/mcp/serve/[serverId]/sse/route.ts @@ -3,8 +3,8 @@ import { workflow, workflowMcpServer, workflowMcpTool } from '@sim/db/schema' import { eq } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { checkHybridAuth } from '@/lib/auth/hybrid' -import { getBaseUrl } from '@/lib/core/utils/urls' import { SSE_HEADERS } from '@/lib/core/utils/sse' +import { getBaseUrl } from '@/lib/core/utils/urls' import { createLogger } from '@/lib/logs/console/logger' const logger = createLogger('WorkflowMcpSSE') @@ -54,10 +54,7 @@ async function validateServer(serverId: string) { * GET - SSE endpoint for MCP protocol * This establishes a Server-Sent Events connection for bidirectional MCP communication */ -export async function GET( - request: NextRequest, - { params }: { params: Promise } -) { +export async function GET(request: NextRequest, { params }: { params: Promise }) { const { serverId } = await params try { @@ -160,10 +157,7 @@ export async function GET( * POST - Handle messages sent to the SSE endpoint * This is used for the message channel in MCP streamable-http transport */ -export async function POST( - request: NextRequest, - { params }: { params: Promise } -) { +export async function POST(request: NextRequest, { params }: { params: Promise }) { const { serverId } = await params try { @@ -224,7 +218,9 @@ export async function POST( case 'tools/call': { // Get the API key from the request to forward to the workflow execute call - const apiKey = request.headers.get('X-API-Key') || request.headers.get('Authorization')?.replace('Bearer ', '') + const apiKey = + request.headers.get('X-API-Key') || + request.headers.get('Authorization')?.replace('Bearer ', '') return handleToolsCall(message, serverId, userId, workspaceId, apiKey) } @@ -258,10 +254,7 @@ export async function POST( /** * Handle tools/list method */ -async function handleToolsList( - id: string | number, - serverId: string -): Promise { +async function handleToolsList(id: string | number, serverId: string): Promise { const tools = await db .select({ toolName: workflowMcpTool.toolName, @@ -369,7 +362,7 @@ async function handleToolsCall( const executeHeaders: Record = { 'Content-Type': 'application/json', } - + // Forward the API key for authentication if (apiKey) { executeHeaders['X-API-Key'] = apiKey diff --git a/apps/sim/app/api/mcp/workflow-servers/[id]/publish/route.ts b/apps/sim/app/api/mcp/workflow-servers/[id]/publish/route.ts index 9980c43ef8..3b6a63ef20 100644 --- a/apps/sim/app/api/mcp/workflow-servers/[id]/publish/route.ts +++ b/apps/sim/app/api/mcp/workflow-servers/[id]/publish/route.ts @@ -54,7 +54,9 @@ export const POST = withMcpAuth('admin')( if (tools.length === 0) { return createMcpErrorResponse( - new Error('Cannot publish server without any tools. Add at least one workflow as a tool first.'), + new Error( + 'Cannot publish server without any tools. Add at least one workflow as a tool first.' + ), 'Server has no tools', 400 ) diff --git a/apps/sim/app/api/mcp/workflow-servers/[id]/route.ts b/apps/sim/app/api/mcp/workflow-servers/[id]/route.ts index 91ffb7760d..4ba78fa656 100644 --- a/apps/sim/app/api/mcp/workflow-servers/[id]/route.ts +++ b/apps/sim/app/api/mcp/workflow-servers/[id]/route.ts @@ -1,6 +1,6 @@ import { db } from '@sim/db' import { workflowMcpServer, workflowMcpTool } from '@sim/db/schema' -import { and, eq, sql } from 'drizzle-orm' +import { and, eq } from 'drizzle-orm' import type { NextRequest } from 'next/server' import { createLogger } from '@/lib/logs/console/logger' import { getParsedBody, withMcpAuth } from '@/lib/mcp/middleware' @@ -51,7 +51,9 @@ export const GET = withMcpAuth('read')( .from(workflowMcpTool) .where(eq(workflowMcpTool.serverId, serverId)) - logger.info(`[${requestId}] Found workflow MCP server: ${server.name} with ${tools.length} tools`) + logger.info( + `[${requestId}] Found workflow MCP server: ${server.name} with ${tools.length} tools` + ) return createMcpSuccessResponse({ server, tools }) } catch (error) { diff --git a/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts b/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts index f07cacb179..eecd27e0c2 100644 --- a/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts +++ b/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts @@ -20,13 +20,15 @@ interface RouteParams { * Tool names should be lowercase, alphanumeric with underscores. */ function sanitizeToolName(name: string): string { - return name - .toLowerCase() - .replace(/[^a-z0-9\s_-]/g, '') - .replace(/[\s-]+/g, '_') - .replace(/_+/g, '_') - .replace(/^_|_$/g, '') - .substring(0, 64) || 'workflow_tool' + return ( + name + .toLowerCase() + .replace(/[^a-z0-9\s_-]/g, '') + .replace(/[\s-]+/g, '_') + .replace(/_+/g, '_') + .replace(/^_|_$/g, '') + .substring(0, 64) || 'workflow_tool' + ) } /** @@ -217,7 +219,9 @@ export const POST = withMcpAuth('write')( // Generate tool name and description const toolName = body.toolName?.trim() || sanitizeToolName(workflowRecord.name) const toolDescription = - body.toolDescription?.trim() || workflowRecord.description || `Execute ${workflowRecord.name} workflow` + body.toolDescription?.trim() || + workflowRecord.description || + `Execute ${workflowRecord.name} workflow` // Create the tool const toolId = crypto.randomUUID() diff --git a/apps/sim/app/api/mcp/workflow-servers/route.ts b/apps/sim/app/api/mcp/workflow-servers/route.ts index 3735ec41f0..8da34710e7 100644 --- a/apps/sim/app/api/mcp/workflow-servers/route.ts +++ b/apps/sim/app/api/mcp/workflow-servers/route.ts @@ -1,6 +1,6 @@ import { db } from '@sim/db' -import { workflowMcpServer, workflowMcpTool } from '@sim/db/schema' -import { and, eq, sql } from 'drizzle-orm' +import { workflowMcpServer } from '@sim/db/schema' +import { eq, sql } from 'drizzle-orm' import type { NextRequest } from 'next/server' import { createLogger } from '@/lib/logs/console/logger' import { getParsedBody, withMcpAuth } from '@/lib/mcp/middleware' diff --git a/apps/sim/app/api/workflows/[id]/deploy/route.ts b/apps/sim/app/api/workflows/[id]/deploy/route.ts index cef214f561..be390f5904 100644 --- a/apps/sim/app/api/workflows/[id]/deploy/route.ts +++ b/apps/sim/app/api/workflows/[id]/deploy/route.ts @@ -138,11 +138,11 @@ async function syncMcpToolsOnDeploy(workflowId: string, requestId: string): Prom const hasStart = await hasValidStartBlock(workflowId) if (!hasStart) { // No start block - remove all MCP tools for this workflow - await db - .delete(workflowMcpTool) - .where(eq(workflowMcpTool.workflowId, workflowId)) - - logger.info(`[${requestId}] Removed ${tools.length} MCP tool(s) - workflow no longer has a start block: ${workflowId}`) + await db.delete(workflowMcpTool).where(eq(workflowMcpTool.workflowId, workflowId)) + + logger.info( + `[${requestId}] Removed ${tools.length} MCP tool(s) - workflow no longer has a start block: ${workflowId}` + ) return } diff --git a/apps/sim/app/api/workflows/[id]/deployments/[version]/activate/route.ts b/apps/sim/app/api/workflows/[id]/deployments/[version]/activate/route.ts index 6ab51a4587..ea8324e5a0 100644 --- a/apps/sim/app/api/workflows/[id]/deployments/[version]/activate/route.ts +++ b/apps/sim/app/api/workflows/[id]/deployments/[version]/activate/route.ts @@ -133,11 +133,11 @@ async function syncMcpToolsOnVersionActivate( // Check if the activated version has a valid start block if (!hasValidStartBlockInState(versionState)) { // No start block - remove all MCP tools for this workflow - await db - .delete(workflowMcpTool) - .where(eq(workflowMcpTool.workflowId, workflowId)) - - logger.info(`[${requestId}] Removed ${tools.length} MCP tool(s) - activated version has no start block: ${workflowId}`) + await db.delete(workflowMcpTool).where(eq(workflowMcpTool.workflowId, workflowId)) + + logger.info( + `[${requestId}] Removed ${tools.length} MCP tool(s) - activated version has no start block: ${workflowId}` + ) return } @@ -153,7 +153,9 @@ async function syncMcpToolsOnVersionActivate( }) .where(eq(workflowMcpTool.workflowId, workflowId)) - logger.info(`[${requestId}] Synced ${tools.length} MCP tool(s) for workflow version activation: ${workflowId}`) + logger.info( + `[${requestId}] Synced ${tools.length} MCP tool(s) for workflow version activation: ${workflowId}` + ) } catch (error) { logger.error(`[${requestId}] Error syncing MCP tools on version activate:`, error) // Don't throw - this is a non-critical operation diff --git a/apps/sim/app/api/workflows/[id]/deployments/[version]/revert/route.ts b/apps/sim/app/api/workflows/[id]/deployments/[version]/revert/route.ts index 5874791516..f645a23450 100644 --- a/apps/sim/app/api/workflows/[id]/deployments/[version]/revert/route.ts +++ b/apps/sim/app/api/workflows/[id]/deployments/[version]/revert/route.ts @@ -135,11 +135,11 @@ async function syncMcpToolsOnRevert( // Check if the reverted version has a valid start block if (!hasValidStartBlockInState(versionState)) { // No start block - remove all MCP tools for this workflow - await db - .delete(workflowMcpTool) - .where(eq(workflowMcpTool.workflowId, workflowId)) - - logger.info(`[${requestId}] Removed ${tools.length} MCP tool(s) - reverted version has no start block: ${workflowId}`) + await db.delete(workflowMcpTool).where(eq(workflowMcpTool.workflowId, workflowId)) + + logger.info( + `[${requestId}] Removed ${tools.length} MCP tool(s) - reverted version has no start block: ${workflowId}` + ) return } @@ -155,7 +155,9 @@ async function syncMcpToolsOnRevert( }) .where(eq(workflowMcpTool.workflowId, workflowId)) - logger.info(`[${requestId}] Synced ${tools.length} MCP tool(s) for workflow revert: ${workflowId}`) + logger.info( + `[${requestId}] Synced ${tools.length} MCP tool(s) for workflow revert: ${workflowId}` + ) } catch (error) { logger.error(`[${requestId}] Error syncing MCP tools on revert:`, error) // Don't throw - this is a non-critical operation diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx index 37a9a67c3b..4c32b3eb4d 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx @@ -1,7 +1,15 @@ 'use client' import { useCallback, useEffect, useMemo, useState } from 'react' -import { AlertTriangle, Check, ChevronDown, ChevronRight, Plus, RefreshCw, Server, Trash2 } from 'lucide-react' +import { + AlertTriangle, + ChevronDown, + ChevronRight, + Plus, + RefreshCw, + Server, + Trash2, +} from 'lucide-react' import { useParams } from 'next/navigation' import { Badge, @@ -42,20 +50,24 @@ interface McpToolDeployProps { * Sanitize a workflow name to be a valid MCP tool name. */ function sanitizeToolName(name: string): string { - return name - .toLowerCase() - .replace(/[^a-z0-9\s_-]/g, '') - .replace(/[\s-]+/g, '_') - .replace(/_+/g, '_') - .replace(/^_|_$/g, '') - .substring(0, 64) || 'workflow_tool' + return ( + name + .toLowerCase() + .replace(/[^a-z0-9\s_-]/g, '') + .replace(/[\s-]+/g, '_') + .replace(/_+/g, '_') + .replace(/^_|_$/g, '') + .substring(0, 64) || 'workflow_tool' + ) } /** * Extract input format from workflow blocks using SubBlockStore * The actual input format values are stored in useSubBlockStore, not directly in the block structure */ -function extractInputFormat(blocks: Record): Array<{ name: string; type: string }> { +function extractInputFormat( + blocks: Record +): Array<{ name: string; type: string }> { // Find the starter block for (const [blockId, block] of Object.entries(blocks)) { if (!block || typeof block !== 'object') continue @@ -67,7 +79,7 @@ function extractInputFormat(blocks: Record): Array<{ name: stri if ( blockType === 'starter' || blockType === 'start' || - blockType === 'start_trigger' || // This is the unified start block type + blockType === 'start_trigger' || // This is the unified start block type blockType === 'api' || blockType === 'api_trigger' || blockType === 'input_trigger' @@ -325,7 +337,10 @@ function ToolOnServer({ )} {needsUpdate && ( - + Needs Update @@ -339,7 +354,12 @@ function ToolOnServer({ disabled={updateToolMutation.isPending} className='h-[24px] px-[8px] text-[11px] text-amber-500 hover:text-amber-600' > - + {updateToolMutation.isPending ? 'Updating...' : 'Update'} )} @@ -354,14 +374,18 @@ function ToolOnServer({ {showDetails && ( -
+
Tool Name - {tool.toolName} + + {tool.toolName} +
- Description + + Description + {tool.toolDescription || '—'} @@ -399,12 +423,16 @@ export function McpToolDeploy({ const params = useParams() const workspaceId = params.workspaceId as string - const { data: servers = [], isLoading: isLoadingServers, refetch: refetchServers } = useWorkflowMcpServers(workspaceId) + const { + data: servers = [], + isLoading: isLoadingServers, + refetch: refetchServers, + } = useWorkflowMcpServers(workspaceId) const addToolMutation = useAddWorkflowMcpTool() // Get workflow blocks const blocks = useWorkflowStore((state) => state.blocks) - + // Find the starter block ID to subscribe to its inputFormat changes const starterBlockId = useMemo(() => { for (const [blockId, block] of Object.entries(blocks)) { @@ -414,7 +442,7 @@ export function McpToolDeploy({ if ( blockType === 'starter' || blockType === 'start' || - blockType === 'start_trigger' || // This is the unified start block type + blockType === 'start_trigger' || // This is the unified start block type blockType === 'api' || blockType === 'api_trigger' || blockType === 'input_trigger' @@ -428,7 +456,7 @@ export function McpToolDeploy({ // Subscribe to the inputFormat value in SubBlockStore for reactivity // Use workflowId prop directly (not activeWorkflowId from registry) to ensure we get the correct workflow's data const subBlockValues = useSubBlockStore((state) => - workflowId ? state.workflowValues[workflowId] ?? {} : {} + workflowId ? (state.workflowValues[workflowId] ?? {}) : {} ) // Extract and normalize input format - now reactive to SubBlockStore changes @@ -436,7 +464,7 @@ export function McpToolDeploy({ // First try to get from SubBlockStore (where runtime values are stored) if (starterBlockId && subBlockValues[starterBlockId]) { const inputFormatValue = subBlockValues[starterBlockId].inputFormat - + if (Array.isArray(inputFormatValue) && inputFormatValue.length > 0) { const filtered = inputFormatValue .filter( @@ -461,7 +489,7 @@ export function McpToolDeploy({ if (starterBlockId && blocks[starterBlockId]) { const startBlock = blocks[starterBlockId] const subBlocksValue = startBlock?.subBlocks?.inputFormat?.value as unknown - + if (Array.isArray(subBlocksValue) && subBlocksValue.length > 0) { const validFields: Array<{ name: string; type: string }> = [] for (const field of subBlocksValue) { @@ -497,22 +525,27 @@ export function McpToolDeploy({ const [showParameterSchema, setShowParameterSchema] = useState(false) // Track tools data from each server using state instead of hooks in a loop - const [serverToolsMap, setServerToolsMap] = useState>({}) + const [serverToolsMap, setServerToolsMap] = useState< + Record + >({}) // Stable callback to handle tool data from ServerToolsQuery components - const handleServerToolData = useCallback((serverId: string, tool: WorkflowMcpTool | null, isLoading: boolean) => { - setServerToolsMap((prev) => { - // Only update if data has changed to prevent infinite loops - const existing = prev[serverId] - if (existing?.tool?.id === tool?.id && existing?.isLoading === isLoading) { - return prev - } - return { - ...prev, - [serverId]: { tool, isLoading }, - } - }) - }, []) + const handleServerToolData = useCallback( + (serverId: string, tool: WorkflowMcpTool | null, isLoading: boolean) => { + setServerToolsMap((prev) => { + // Only update if data has changed to prevent infinite loops + const existing = prev[serverId] + if (existing?.tool?.id === tool?.id && existing?.isLoading === isLoading) { + return prev + } + return { + ...prev, + [serverId]: { tool, isLoading }, + } + }) + }, + [] + ) // Find which servers already have this workflow as a tool and get the tool info const serversWithThisWorkflow = useMemo(() => { @@ -555,7 +588,7 @@ export function McpToolDeploy({ setSelectedServer(null) setToolName('') setToolDescription('') - + // Refetch servers to update tool count refetchServers() onAddedToServer?.() @@ -576,18 +609,21 @@ export function McpToolDeploy({ onAddedToServer, ]) - const handleToolChanged = useCallback((removedServerId?: string) => { - // If a tool was removed from a specific server, clear just that entry - // The ServerToolsQuery component will re-query and update the map - if (removedServerId) { - setServerToolsMap((prev) => { - const next = { ...prev } - delete next[removedServerId] - return next - }) - } - refetchServers() - }, [refetchServers]) + const handleToolChanged = useCallback( + (removedServerId?: string) => { + // If a tool was removed from a specific server, clear just that entry + // The ServerToolsQuery component will re-query and update the map + if (removedServerId) { + setServerToolsMap((prev) => { + const next = { ...prev } + delete next[removedServerId] + return next + }) + } + refetchServers() + }, + [refetchServers] + ) const availableServers = useMemo(() => { const addedServerIds = new Set(serversWithThisWorkflow.map((s) => s.server.id)) @@ -646,7 +682,8 @@ export function McpToolDeploy({

- Add this workflow as an MCP tool to make it callable by external MCP clients like Cursor or Claude Desktop. + Add this workflow as an MCP tool to make it callable by external MCP clients like Cursor + or Claude Desktop.

@@ -655,8 +692,8 @@ export function McpToolDeploy({

- {toolsNeedingUpdate.length} server{toolsNeedingUpdate.length > 1 ? 's have' : ' has'} outdated tool - definitions. Click "Update" on each to sync with current parameters. + {toolsNeedingUpdate.length} server{toolsNeedingUpdate.length > 1 ? 's have' : ' has'}{' '} + outdated tool definitions. Click "Update" on each to sync with current parameters.

)} @@ -677,12 +714,13 @@ export function McpToolDeploy({ Current Tool Parameters ({inputFormat.length}) - + {showParameterSchema && (
{inputFormat.length === 0 ? (

- No parameters defined. Add input fields in the Starter block to define tool parameters. + No parameters defined. Add input fields in the Starter block to define tool + parameters.

) : (
diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/workflow-mcp-servers/workflow-mcp-servers.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/workflow-mcp-servers/workflow-mcp-servers.tsx index bff7f32bd9..ff9ee17fec 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/workflow-mcp-servers/workflow-mcp-servers.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/workflow-mcp-servers/workflow-mcp-servers.tsx @@ -179,7 +179,9 @@ function ServerDetailView({ workspaceId, serverId, onBack }: ServerDetailViewPro
- Server Name + + Server Name +

{server.name}

@@ -317,7 +319,9 @@ function ServerDetailView({ workspaceId, serverId, onBack }: ServerDetailViewPro

Are you sure you want to remove{' '} - {toolToDelete?.toolName}{' '} + + {toolToDelete?.toolName} + {' '} from this server?

@@ -464,10 +468,14 @@ export function WorkflowMcpServers() {
-
-
@@ -551,7 +565,8 @@ export function WorkflowMcpServers() {

Are you sure you want to delete{' '} - {serverToDelete?.name}?{' '} + {serverToDelete?.name} + ?{' '} This will remove all tools and cannot be undone. diff --git a/apps/sim/hooks/queries/workflow-mcp-servers.ts b/apps/sim/hooks/queries/workflow-mcp-servers.ts index 18682e3349..8884a18015 100644 --- a/apps/sim/hooks/queries/workflow-mcp-servers.ts +++ b/apps/sim/hooks/queries/workflow-mcp-servers.ts @@ -208,11 +208,14 @@ export function useUpdateWorkflowMcpServer() { name, description, }: UpdateWorkflowMcpServerParams) => { - const response = await fetch(`/api/mcp/workflow-servers/${serverId}?workspaceId=${workspaceId}`, { - method: 'PATCH', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ name, description }), - }) + const response = await fetch( + `/api/mcp/workflow-servers/${serverId}?workspaceId=${workspaceId}`, + { + method: 'PATCH', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ name, description }), + } + ) const data = await response.json() diff --git a/apps/sim/lib/core/rate-limiter/types.ts b/apps/sim/lib/core/rate-limiter/types.ts index 118614eb17..8932e853d0 100644 --- a/apps/sim/lib/core/rate-limiter/types.ts +++ b/apps/sim/lib/core/rate-limiter/types.ts @@ -1,7 +1,14 @@ import { env } from '@/lib/core/config/env' import type { TokenBucketConfig } from './storage' -export type TriggerType = 'api' | 'webhook' | 'schedule' | 'manual' | 'chat' | 'mcp' | 'api-endpoint' +export type TriggerType = + | 'api' + | 'webhook' + | 'schedule' + | 'manual' + | 'chat' + | 'mcp' + | 'api-endpoint' export type RateLimitCounterType = 'sync' | 'async' | 'api-endpoint' diff --git a/apps/sim/lib/mcp/workflow-tool-schema.ts b/apps/sim/lib/mcp/workflow-tool-schema.ts index 4f20bd7d07..e54482fbd3 100644 --- a/apps/sim/lib/mcp/workflow-tool-schema.ts +++ b/apps/sim/lib/mcp/workflow-tool-schema.ts @@ -49,13 +49,15 @@ function mapFieldTypeToJsonSchemaType(fieldType: string | undefined): string { * Tool names should be lowercase, alphanumeric with underscores. */ export function sanitizeToolName(name: string): string { - return name - .toLowerCase() - .replace(/[^a-z0-9\s_-]/g, '') - .replace(/[\s-]+/g, '_') - .replace(/_+/g, '_') - .replace(/^_|_$/g, '') - .substring(0, 64) || 'workflow_tool' + return ( + name + .toLowerCase() + .replace(/[^a-z0-9\s_-]/g, '') + .replace(/[\s-]+/g, '_') + .replace(/_+/g, '_') + .replace(/^_|_$/g, '') + .substring(0, 64) || 'workflow_tool' + ) } /** diff --git a/apps/sim/stores/logs/filters/store.ts b/apps/sim/stores/logs/filters/store.ts index 245c6038a0..134295cf37 100644 --- a/apps/sim/stores/logs/filters/store.ts +++ b/apps/sim/stores/logs/filters/store.ts @@ -60,7 +60,9 @@ const parseTriggerArrayFromURL = (value: string | null): TriggerType[] => { if (!value) return [] return value .split(',') - .filter((t): t is TriggerType => ['chat', 'api', 'webhook', 'manual', 'schedule', 'mcp'].includes(t)) + .filter((t): t is TriggerType => + ['chat', 'api', 'webhook', 'manual', 'schedule', 'mcp'].includes(t) + ) } const parseStringArrayFromURL = (value: string | null): string[] => { diff --git a/apps/sim/stores/logs/filters/types.ts b/apps/sim/stores/logs/filters/types.ts index 249fe4b557..f9752133ee 100644 --- a/apps/sim/stores/logs/filters/types.ts +++ b/apps/sim/stores/logs/filters/types.ts @@ -166,7 +166,15 @@ export type TimeRange = | 'Past 30 days' | 'All time' export type LogLevel = 'error' | 'info' | 'running' | 'pending' | 'all' -export type TriggerType = 'chat' | 'api' | 'webhook' | 'manual' | 'schedule' | 'mcp' | 'all' | string +export type TriggerType = + | 'chat' + | 'api' + | 'webhook' + | 'manual' + | 'schedule' + | 'mcp' + | 'all' + | string export interface FilterState { // Workspace context diff --git a/packages/db/migrations/meta/0123_snapshot.json b/packages/db/migrations/meta/0123_snapshot.json index 71584ca6aa..7e57688b5e 100644 --- a/packages/db/migrations/meta/0123_snapshot.json +++ b/packages/db/migrations/meta/0123_snapshot.json @@ -157,12 +157,8 @@ "name": "account_user_id_user_id_fk", "tableFrom": "account", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -253,12 +249,8 @@ "name": "api_key_user_id_user_id_fk", "tableFrom": "api_key", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -266,12 +258,8 @@ "name": "api_key_workspace_id_workspace_id_fk", "tableFrom": "api_key", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -279,12 +267,8 @@ "name": "api_key_created_by_user_id_fk", "tableFrom": "api_key", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -294,9 +278,7 @@ "api_key_key_unique": { "name": "api_key_key_unique", "nullsNotDistinct": false, - "columns": [ - "key" - ] + "columns": ["key"] } }, "policies": {}, @@ -426,12 +408,8 @@ "name": "chat_workflow_id_workflow_id_fk", "tableFrom": "chat", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -439,12 +417,8 @@ "name": "chat_user_id_user_id_fk", "tableFrom": "chat", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -625,12 +599,8 @@ "name": "copilot_chats_user_id_user_id_fk", "tableFrom": "copilot_chats", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -638,12 +608,8 @@ "name": "copilot_chats_workflow_id_workflow_id_fk", "tableFrom": "copilot_chats", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -810,12 +776,8 @@ "name": "copilot_feedback_user_id_user_id_fk", "tableFrom": "copilot_feedback", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -823,12 +785,8 @@ "name": "copilot_feedback_chat_id_copilot_chats_id_fk", "tableFrom": "copilot_feedback", "tableTo": "copilot_chats", - "columnsFrom": [ - "chat_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["chat_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -937,12 +895,8 @@ "name": "custom_tools_workspace_id_workspace_id_fk", "tableFrom": "custom_tools", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -950,12 +904,8 @@ "name": "custom_tools_user_id_user_id_fk", "tableFrom": "custom_tools", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -1518,12 +1468,8 @@ "name": "document_knowledge_base_id_knowledge_base_id_fk", "tableFrom": "document", "tableTo": "knowledge_base", - "columnsFrom": [ - "knowledge_base_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -1945,12 +1891,8 @@ "name": "embedding_knowledge_base_id_knowledge_base_id_fk", "tableFrom": "embedding", "tableTo": "knowledge_base", - "columnsFrom": [ - "knowledge_base_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -1958,12 +1900,8 @@ "name": "embedding_document_id_document_id_fk", "tableFrom": "embedding", "tableTo": "document", - "columnsFrom": [ - "document_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["document_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2015,12 +1953,8 @@ "name": "environment_user_id_user_id_fk", "tableFrom": "environment", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2030,9 +1964,7 @@ "environment_user_id_unique": { "name": "environment_user_id_unique", "nullsNotDistinct": false, - "columns": [ - "user_id" - ] + "columns": ["user_id"] } }, "policies": {}, @@ -2221,12 +2153,8 @@ "name": "invitation_inviter_id_user_id_fk", "tableFrom": "invitation", "tableTo": "user", - "columnsFrom": [ - "inviter_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["inviter_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2234,12 +2162,8 @@ "name": "invitation_organization_id_organization_id_fk", "tableFrom": "invitation", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2406,12 +2330,8 @@ "name": "knowledge_base_user_id_user_id_fk", "tableFrom": "knowledge_base", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2419,12 +2339,8 @@ "name": "knowledge_base_workspace_id_workspace_id_fk", "tableFrom": "knowledge_base", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" } @@ -2549,12 +2465,8 @@ "name": "knowledge_base_tag_definitions_knowledge_base_id_knowledge_base_id_fk", "tableFrom": "knowledge_base_tag_definitions", "tableTo": "knowledge_base", - "columnsFrom": [ - "knowledge_base_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2754,12 +2666,8 @@ "name": "mcp_servers_workspace_id_workspace_id_fk", "tableFrom": "mcp_servers", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2767,12 +2675,8 @@ "name": "mcp_servers_created_by_user_id_fk", "tableFrom": "mcp_servers", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -2856,12 +2760,8 @@ "name": "member_user_id_user_id_fk", "tableFrom": "member", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2869,12 +2769,8 @@ "name": "member_organization_id_organization_id_fk", "tableFrom": "member", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2992,12 +2888,8 @@ "name": "memory_workflow_id_workflow_id_fk", "tableFrom": "memory", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3226,12 +3118,8 @@ "name": "paused_executions_workflow_id_workflow_id_fk", "tableFrom": "paused_executions", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3437,12 +3325,8 @@ "name": "permissions_user_id_user_id_fk", "tableFrom": "permissions", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3613,12 +3497,8 @@ "name": "resume_queue_paused_execution_id_paused_executions_id_fk", "tableFrom": "resume_queue", "tableTo": "paused_executions", - "columnsFrom": [ - "paused_execution_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["paused_execution_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3725,12 +3605,8 @@ "name": "session_user_id_user_id_fk", "tableFrom": "session", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -3738,12 +3614,8 @@ "name": "session_active_organization_id_organization_id_fk", "tableFrom": "session", "tableTo": "organization", - "columnsFrom": [ - "active_organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["active_organization_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -3753,9 +3625,7 @@ "session_token_unique": { "name": "session_token_unique", "nullsNotDistinct": false, - "columns": [ - "token" - ] + "columns": ["token"] } }, "policies": {}, @@ -3862,12 +3732,8 @@ "name": "settings_user_id_user_id_fk", "tableFrom": "settings", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3877,9 +3743,7 @@ "settings_user_id_unique": { "name": "settings_user_id_unique", "nullsNotDistinct": false, - "columns": [ - "user_id" - ] + "columns": ["user_id"] } }, "policies": {}, @@ -4006,12 +3870,8 @@ "name": "sso_provider_user_id_user_id_fk", "tableFrom": "sso_provider", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -4019,12 +3879,8 @@ "name": "sso_provider_organization_id_organization_id_fk", "tableFrom": "sso_provider", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4280,12 +4136,8 @@ "name": "template_creators_created_by_user_id_fk", "tableFrom": "template_creators", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -4469,12 +4321,8 @@ "name": "template_stars_user_id_user_id_fk", "tableFrom": "template_stars", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -4482,12 +4330,8 @@ "name": "template_stars_template_id_templates_id_fk", "tableFrom": "template_stars", "tableTo": "templates", - "columnsFrom": [ - "template_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["template_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4728,12 +4572,8 @@ "name": "templates_workflow_id_workflow_id_fk", "tableFrom": "templates", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -4741,12 +4581,8 @@ "name": "templates_creator_id_template_creators_id_fk", "tableFrom": "templates", "tableTo": "template_creators", - "columnsFrom": [ - "creator_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["creator_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -4824,9 +4660,7 @@ "user_email_unique": { "name": "user_email_unique", "nullsNotDistinct": false, - "columns": [ - "email" - ] + "columns": ["email"] } }, "policies": {}, @@ -5017,12 +4851,8 @@ "name": "user_stats_user_id_user_id_fk", "tableFrom": "user_stats", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -5032,9 +4862,7 @@ "user_stats_user_id_unique": { "name": "user_stats_user_id_unique", "nullsNotDistinct": false, - "columns": [ - "user_id" - ] + "columns": ["user_id"] } }, "policies": {}, @@ -5151,9 +4979,7 @@ "waitlist_email_unique": { "name": "waitlist_email_unique", "nullsNotDistinct": false, - "columns": [ - "email" - ] + "columns": ["email"] } }, "policies": {}, @@ -5278,12 +5104,8 @@ "name": "webhook_workflow_id_workflow_id_fk", "tableFrom": "webhook", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5291,12 +5113,8 @@ "name": "webhook_block_id_workflow_blocks_id_fk", "tableFrom": "webhook", "tableTo": "workflow_blocks", - "columnsFrom": [ - "block_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["block_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -5464,12 +5282,8 @@ "name": "workflow_user_id_user_id_fk", "tableFrom": "workflow", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5477,12 +5291,8 @@ "name": "workflow_workspace_id_workspace_id_fk", "tableFrom": "workflow", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5490,12 +5300,8 @@ "name": "workflow_folder_id_workflow_folder_id_fk", "tableFrom": "workflow", "tableTo": "workflow_folder", - "columnsFrom": [ - "folder_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["folder_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -5646,12 +5452,8 @@ "name": "workflow_blocks_workflow_id_workflow_id_fk", "tableFrom": "workflow_blocks", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -5863,12 +5665,8 @@ "name": "workflow_checkpoints_user_id_user_id_fk", "tableFrom": "workflow_checkpoints", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5876,12 +5674,8 @@ "name": "workflow_checkpoints_workflow_id_workflow_id_fk", "tableFrom": "workflow_checkpoints", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5889,12 +5683,8 @@ "name": "workflow_checkpoints_chat_id_copilot_chats_id_fk", "tableFrom": "workflow_checkpoints", "tableTo": "copilot_chats", - "columnsFrom": [ - "chat_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["chat_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -6024,12 +5814,8 @@ "name": "workflow_deployment_version_workflow_id_workflow_id_fk", "tableFrom": "workflow_deployment_version", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -6152,12 +5938,8 @@ "name": "workflow_edges_workflow_id_workflow_id_fk", "tableFrom": "workflow_edges", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -6165,12 +5947,8 @@ "name": "workflow_edges_source_block_id_workflow_blocks_id_fk", "tableFrom": "workflow_edges", "tableTo": "workflow_blocks", - "columnsFrom": [ - "source_block_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["source_block_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -6178,12 +5956,8 @@ "name": "workflow_edges_target_block_id_workflow_blocks_id_fk", "tableFrom": "workflow_edges", "tableTo": "workflow_blocks", - "columnsFrom": [ - "target_block_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["target_block_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -6418,12 +6192,8 @@ "name": "workflow_execution_logs_workflow_id_workflow_id_fk", "tableFrom": "workflow_execution_logs", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -6431,12 +6201,8 @@ "name": "workflow_execution_logs_state_snapshot_id_workflow_execution_snapshots_id_fk", "tableFrom": "workflow_execution_logs", "tableTo": "workflow_execution_snapshots", - "columnsFrom": [ - "state_snapshot_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["state_snapshot_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" }, @@ -6444,12 +6210,8 @@ "name": "workflow_execution_logs_deployment_version_id_workflow_deployment_version_id_fk", "tableFrom": "workflow_execution_logs", "tableTo": "workflow_deployment_version", - "columnsFrom": [ - "deployment_version_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["deployment_version_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -6569,12 +6331,8 @@ "name": "workflow_execution_snapshots_workflow_id_workflow_id_fk", "tableFrom": "workflow_execution_snapshots", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -6719,12 +6477,8 @@ "name": "workflow_folder_user_id_user_id_fk", "tableFrom": "workflow_folder", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -6732,12 +6486,8 @@ "name": "workflow_folder_workspace_id_workspace_id_fk", "tableFrom": "workflow_folder", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -6862,12 +6612,8 @@ "name": "workflow_mcp_server_workspace_id_workspace_id_fk", "tableFrom": "workflow_mcp_server", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -6875,12 +6621,8 @@ "name": "workflow_mcp_server_created_by_user_id_fk", "tableFrom": "workflow_mcp_server", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -7012,12 +6754,8 @@ "name": "workflow_mcp_tool_server_id_workflow_mcp_server_id_fk", "tableFrom": "workflow_mcp_tool", "tableTo": "workflow_mcp_server", - "columnsFrom": [ - "server_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["server_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -7025,12 +6763,8 @@ "name": "workflow_mcp_tool_workflow_id_workflow_id_fk", "tableFrom": "workflow_mcp_tool", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -7163,12 +6897,8 @@ "name": "workflow_schedule_workflow_id_workflow_id_fk", "tableFrom": "workflow_schedule", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -7176,12 +6906,8 @@ "name": "workflow_schedule_block_id_workflow_blocks_id_fk", "tableFrom": "workflow_schedule", "tableTo": "workflow_blocks", - "columnsFrom": [ - "block_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["block_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -7279,12 +7005,8 @@ "name": "workflow_subflows_workflow_id_workflow_id_fk", "tableFrom": "workflow_subflows", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -7351,12 +7073,8 @@ "name": "workspace_owner_id_user_id_fk", "tableFrom": "workspace", "tableTo": "user", - "columnsFrom": [ - "owner_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["owner_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -7364,12 +7082,8 @@ "name": "workspace_billed_account_user_id_user_id_fk", "tableFrom": "workspace", "tableTo": "user", - "columnsFrom": [ - "billed_account_user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["billed_account_user_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" } @@ -7440,12 +7154,8 @@ "name": "workspace_environment_workspace_id_workspace_id_fk", "tableFrom": "workspace_environment", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -7547,12 +7257,8 @@ "name": "workspace_file_workspace_id_workspace_id_fk", "tableFrom": "workspace_file", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -7560,12 +7266,8 @@ "name": "workspace_file_uploaded_by_user_id_fk", "tableFrom": "workspace_file", "tableTo": "user", - "columnsFrom": [ - "uploaded_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["uploaded_by"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -7575,9 +7277,7 @@ "workspace_file_key_unique": { "name": "workspace_file_key_unique", "nullsNotDistinct": false, - "columns": [ - "key" - ] + "columns": ["key"] } }, "policies": {}, @@ -7711,12 +7411,8 @@ "name": "workspace_files_user_id_user_id_fk", "tableFrom": "workspace_files", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -7724,12 +7420,8 @@ "name": "workspace_files_workspace_id_workspace_id_fk", "tableFrom": "workspace_files", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -7739,9 +7431,7 @@ "workspace_files_key_unique": { "name": "workspace_files_key_unique", "nullsNotDistinct": false, - "columns": [ - "key" - ] + "columns": ["key"] } }, "policies": {}, @@ -7838,12 +7528,8 @@ "name": "workspace_invitation_workspace_id_workspace_id_fk", "tableFrom": "workspace_invitation", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -7851,12 +7537,8 @@ "name": "workspace_invitation_inviter_id_user_id_fk", "tableFrom": "workspace_invitation", "tableTo": "user", - "columnsFrom": [ - "inviter_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["inviter_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -7866,9 +7548,7 @@ "workspace_invitation_token_unique": { "name": "workspace_invitation_token_unique", "nullsNotDistinct": false, - "columns": [ - "token" - ] + "columns": ["token"] } }, "policies": {}, @@ -8030,12 +7710,8 @@ "name": "workspace_notification_delivery_subscription_id_workspace_notification_subscription_id_fk", "tableFrom": "workspace_notification_delivery", "tableTo": "workspace_notification_subscription", - "columnsFrom": [ - "subscription_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["subscription_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -8043,12 +7719,8 @@ "name": "workspace_notification_delivery_workflow_id_workflow_id_fk", "tableFrom": "workspace_notification_delivery", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -8248,12 +7920,8 @@ "name": "workspace_notification_subscription_workspace_id_workspace_id_fk", "tableFrom": "workspace_notification_subscription", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -8261,12 +7929,8 @@ "name": "workspace_notification_subscription_created_by_user_id_fk", "tableFrom": "workspace_notification_subscription", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -8282,65 +7946,37 @@ "public.billing_blocked_reason": { "name": "billing_blocked_reason", "schema": "public", - "values": [ - "payment_failed", - "dispute" - ] + "values": ["payment_failed", "dispute"] }, "public.notification_delivery_status": { "name": "notification_delivery_status", "schema": "public", - "values": [ - "pending", - "in_progress", - "success", - "failed" - ] + "values": ["pending", "in_progress", "success", "failed"] }, "public.notification_type": { "name": "notification_type", "schema": "public", - "values": [ - "webhook", - "email", - "slack" - ] + "values": ["webhook", "email", "slack"] }, "public.permission_type": { "name": "permission_type", "schema": "public", - "values": [ - "admin", - "write", - "read" - ] + "values": ["admin", "write", "read"] }, "public.template_creator_type": { "name": "template_creator_type", "schema": "public", - "values": [ - "user", - "organization" - ] + "values": ["user", "organization"] }, "public.template_status": { "name": "template_status", "schema": "public", - "values": [ - "pending", - "approved", - "rejected" - ] + "values": ["pending", "approved", "rejected"] }, "public.workspace_invitation_status": { "name": "workspace_invitation_status", "schema": "public", - "values": [ - "pending", - "accepted", - "rejected", - "cancelled" - ] + "values": ["pending", "accepted", "rejected", "cancelled"] } }, "schemas": {}, @@ -8353,4 +7989,4 @@ "schemas": {}, "tables": {} } -} \ No newline at end of file +} diff --git a/packages/db/migrations/meta/_journal.json b/packages/db/migrations/meta/_journal.json index 124b3bf979..4b22dd9e02 100644 --- a/packages/db/migrations/meta/_journal.json +++ b/packages/db/migrations/meta/_journal.json @@ -864,4 +864,4 @@ "breakpoints": true } ] -} \ No newline at end of file +} From 85af04675437250bd44cbc7f5ea60c4b799939d3 Mon Sep 17 00:00:00 2001 From: "priyanshu.solanki" Date: Tue, 16 Dec 2025 19:14:05 -0700 Subject: [PATCH 04/27] using mcn components --- .../mcp/workflow-servers/[id]/tools/route.ts | 17 +----- .../components/mcp-tool/mcp-tool.tsx | 61 +------------------ 2 files changed, 4 insertions(+), 74 deletions(-) diff --git a/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts b/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts index eecd27e0c2..2a668a99c2 100644 --- a/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts +++ b/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts @@ -5,6 +5,7 @@ import type { NextRequest } from 'next/server' import { createLogger } from '@/lib/logs/console/logger' import { getParsedBody, withMcpAuth } from '@/lib/mcp/middleware' import { createMcpErrorResponse, createMcpSuccessResponse } from '@/lib/mcp/utils' +import { sanitizeToolName } from '@/lib/mcp/workflow-tool-schema' import { loadWorkflowFromNormalizedTables } from '@/lib/workflows/persistence/utils' const logger = createLogger('WorkflowMcpToolsAPI') @@ -15,22 +16,6 @@ interface RouteParams { id: string } -/** - * Sanitize a workflow name to be a valid MCP tool name. - * Tool names should be lowercase, alphanumeric with underscores. - */ -function sanitizeToolName(name: string): string { - return ( - name - .toLowerCase() - .replace(/[^a-z0-9\s_-]/g, '') - .replace(/[\s-]+/g, '_') - .replace(/_+/g, '_') - .replace(/^_|_$/g, '') - .substring(0, 64) || 'workflow_tool' - ) -} - /** * Check if a workflow has a valid start block that can accept inputs */ diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx index 4c32b3eb4d..36ac50b6f8 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx @@ -24,6 +24,7 @@ import { import { Skeleton } from '@/components/ui' import { cn } from '@/lib/core/utils/cn' import { createLogger } from '@/lib/logs/console/logger' +import { generateToolInputSchema, sanitizeToolName } from '@/lib/mcp/workflow-tool-schema' import { useAddWorkflowMcpTool, useDeleteWorkflowMcpTool, @@ -46,21 +47,6 @@ interface McpToolDeployProps { onAddedToServer?: () => void } -/** - * Sanitize a workflow name to be a valid MCP tool name. - */ -function sanitizeToolName(name: string): string { - return ( - name - .toLowerCase() - .replace(/[^a-z0-9\s_-]/g, '') - .replace(/[\s-]+/g, '_') - .replace(/_+/g, '_') - .replace(/^_|_$/g, '') - .substring(0, 64) || 'workflow_tool' - ) -} - /** * Extract input format from workflow blocks using SubBlockStore * The actual input format values are stored in useSubBlockStore, not directly in the block structure @@ -131,53 +117,12 @@ function extractInputFormat( } /** - * Generate JSON Schema from input format + * Generate JSON Schema from input format using the shared utility */ function generateParameterSchema( inputFormat: Array<{ name: string; type: string }> ): Record { - if (inputFormat.length === 0) { - return { - type: 'object', - properties: {}, - } - } - - const properties: Record = {} - const required: string[] = [] - - for (const field of inputFormat) { - let jsonType = 'string' - switch (field.type) { - case 'number': - jsonType = 'number' - break - case 'boolean': - jsonType = 'boolean' - break - case 'object': - jsonType = 'object' - break - case 'array': - case 'files': - jsonType = 'array' - break - default: - jsonType = 'string' - } - - properties[field.name] = { - type: jsonType, - description: field.name, - } - required.push(field.name) - } - - return { - type: 'object', - properties, - required, - } + return generateToolInputSchema(inputFormat) as unknown as Record } /** From 2259bfcb8f2ca5aae694e9cc6af195faeed0cc06 Mon Sep 17 00:00:00 2001 From: "priyanshu.solanki" Date: Wed, 17 Dec 2025 17:21:45 -0700 Subject: [PATCH 05/27] fixing merge conflicts --- .../[id]/connection-info/route.ts | 70 - .../sim/hooks/queries/workflow-mcp-servers.ts | 49 - .../db/migrations/meta/0123_snapshot.json | 7992 ----------------- packages/db/migrations/meta/_journal.json | 7 - 4 files changed, 8118 deletions(-) delete mode 100644 apps/sim/app/api/mcp/workflow-servers/[id]/connection-info/route.ts delete mode 100644 packages/db/migrations/meta/0123_snapshot.json diff --git a/apps/sim/app/api/mcp/workflow-servers/[id]/connection-info/route.ts b/apps/sim/app/api/mcp/workflow-servers/[id]/connection-info/route.ts deleted file mode 100644 index 5d0c6766c7..0000000000 --- a/apps/sim/app/api/mcp/workflow-servers/[id]/connection-info/route.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { db } from '@sim/db' -import { workflowMcpServer } from '@sim/db/schema' -import { and, eq } from 'drizzle-orm' -import type { NextRequest } from 'next/server' -import { getBaseUrl } from '@/lib/core/utils/urls' -import { createLogger } from '@/lib/logs/console/logger' -import { withMcpAuth } from '@/lib/mcp/middleware' -import { getMcpServerConnectionInfo } from '@/lib/mcp/serve-auth' -import { createMcpErrorResponse, createMcpSuccessResponse } from '@/lib/mcp/utils' - -const logger = createLogger('WorkflowMcpConnectionInfoAPI') - -export const dynamic = 'force-dynamic' - -interface RouteParams { - id: string -} - -/** - * GET - Get connection info for an MCP server - */ -export const GET = withMcpAuth('read')( - async (request: NextRequest, { userId, workspaceId, requestId }, { params }) => { - try { - const { id: serverId } = await params - - logger.info(`[${requestId}] Getting connection info for server: ${serverId}`) - - const [server] = await db - .select({ - id: workflowMcpServer.id, - name: workflowMcpServer.name, - isPublished: workflowMcpServer.isPublished, - }) - .from(workflowMcpServer) - .where( - and(eq(workflowMcpServer.id, serverId), eq(workflowMcpServer.workspaceId, workspaceId)) - ) - .limit(1) - - if (!server) { - return createMcpErrorResponse(new Error('Server not found'), 'Server not found', 404) - } - - if (!server.isPublished) { - return createMcpErrorResponse( - new Error('Server must be published to get connection info'), - 'Server not published', - 400 - ) - } - - const baseUrl = getBaseUrl() - const connectionInfo = getMcpServerConnectionInfo(serverId, server.name, baseUrl) - - return createMcpSuccessResponse({ - serverId, - serverName: server.name, - ...connectionInfo, - }) - } catch (error) { - logger.error(`[${requestId}] Error getting connection info:`, error) - return createMcpErrorResponse( - error instanceof Error ? error : new Error('Failed to get connection info'), - 'Failed to get connection info', - 500 - ) - } - } -) diff --git a/apps/sim/hooks/queries/workflow-mcp-servers.ts b/apps/sim/hooks/queries/workflow-mcp-servers.ts index 8884a18015..e01048ac44 100644 --- a/apps/sim/hooks/queries/workflow-mcp-servers.ts +++ b/apps/sim/hooks/queries/workflow-mcp-servers.ts @@ -506,52 +506,3 @@ export function useDeleteWorkflowMcpTool() { }, }) } - -/** - * Connection info for an MCP server - */ -export interface WorkflowMcpServerConnectionInfo { - serverId: string - serverName: string - sseUrl: string - httpUrl: string - authHeader: string - instructions: string -} - -/** - * Fetch connection info for a workflow MCP server - */ -async function fetchWorkflowMcpServerConnectionInfo( - workspaceId: string, - serverId: string -): Promise { - const response = await fetch( - `/api/mcp/workflow-servers/${serverId}/connection-info?workspaceId=${workspaceId}` - ) - - const data = await response.json() - - if (!response.ok) { - throw new Error(data.error || 'Failed to fetch connection info') - } - - return data.data -} - -/** - * Hook to fetch connection info for a published MCP server - */ -export function useWorkflowMcpServerConnectionInfo( - workspaceId: string, - serverId: string | null, - enabled = true -) { - return useQuery({ - queryKey: [...workflowMcpServerKeys.server(workspaceId, serverId || ''), 'connection-info'], - queryFn: () => fetchWorkflowMcpServerConnectionInfo(workspaceId, serverId!), - enabled: !!workspaceId && !!serverId && enabled, - retry: false, - staleTime: 5 * 60 * 1000, // 5 minutes - connection info doesn't change often - }) -} diff --git a/packages/db/migrations/meta/0123_snapshot.json b/packages/db/migrations/meta/0123_snapshot.json deleted file mode 100644 index 7e57688b5e..0000000000 --- a/packages/db/migrations/meta/0123_snapshot.json +++ /dev/null @@ -1,7992 +0,0 @@ -{ - "id": "f83e4e1c-3247-4d11-9779-64587c380771", - "prevId": "ec1ad797-549e-4e4e-a40b-f2a865ae4c4c", - "version": "7", - "dialect": "postgresql", - "tables": { - "public.account": { - "name": "account", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "account_id": { - "name": "account_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "provider_id": { - "name": "provider_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "access_token": { - "name": "access_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "refresh_token": { - "name": "refresh_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id_token": { - "name": "id_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "access_token_expires_at": { - "name": "access_token_expires_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "refresh_token_expires_at": { - "name": "refresh_token_expires_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "scope": { - "name": "scope", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "password": { - "name": "password", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - } - }, - "indexes": { - "account_user_id_idx": { - "name": "account_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_account_on_account_id_provider_id": { - "name": "idx_account_on_account_id_provider_id", - "columns": [ - { - "expression": "account_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "provider_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "account_user_provider_account_unique": { - "name": "account_user_provider_account_unique", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "provider_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "account_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "account_user_id_user_id_fk": { - "name": "account_user_id_user_id_fk", - "tableFrom": "account", - "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.api_key": { - "name": "api_key", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "workspace_id": { - "name": "workspace_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_by": { - "name": "created_by", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "key": { - "name": "key", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'personal'" - }, - "last_used": { - "name": "last_used", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "api_key_user_id_user_id_fk": { - "name": "api_key_user_id_user_id_fk", - "tableFrom": "api_key", - "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "api_key_workspace_id_workspace_id_fk": { - "name": "api_key_workspace_id_workspace_id_fk", - "tableFrom": "api_key", - "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "api_key_created_by_user_id_fk": { - "name": "api_key_created_by_user_id_fk", - "tableFrom": "api_key", - "tableTo": "user", - "columnsFrom": ["created_by"], - "columnsTo": ["id"], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "api_key_key_unique": { - "name": "api_key_key_unique", - "nullsNotDistinct": false, - "columns": ["key"] - } - }, - "policies": {}, - "checkConstraints": { - "workspace_type_check": { - "name": "workspace_type_check", - "value": "(type = 'workspace' AND workspace_id IS NOT NULL) OR (type = 'personal' AND workspace_id IS NULL)" - } - }, - "isRLSEnabled": false - }, - "public.chat": { - "name": "chat", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "workflow_id": { - "name": "workflow_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "identifier": { - "name": "identifier", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "title": { - "name": "title", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "is_active": { - "name": "is_active", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "customizations": { - "name": "customizations", - "type": "json", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "auth_type": { - "name": "auth_type", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'public'" - }, - "password": { - "name": "password", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "allowed_emails": { - "name": "allowed_emails", - "type": "json", - "primaryKey": false, - "notNull": false, - "default": "'[]'" - }, - "output_configs": { - "name": "output_configs", - "type": "json", - "primaryKey": false, - "notNull": false, - "default": "'[]'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "identifier_idx": { - "name": "identifier_idx", - "columns": [ - { - "expression": "identifier", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "chat_workflow_id_workflow_id_fk": { - "name": "chat_workflow_id_workflow_id_fk", - "tableFrom": "chat", - "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "chat_user_id_user_id_fk": { - "name": "chat_user_id_user_id_fk", - "tableFrom": "chat", - "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.copilot_chats": { - "name": "copilot_chats", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "workflow_id": { - "name": "workflow_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "title": { - "name": "title", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "messages": { - "name": "messages", - "type": "jsonb", - "primaryKey": false, - "notNull": true, - "default": "'[]'" - }, - "model": { - "name": "model", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'claude-3-7-sonnet-latest'" - }, - "conversation_id": { - "name": "conversation_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "preview_yaml": { - "name": "preview_yaml", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "plan_artifact": { - "name": "plan_artifact", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "config": { - "name": "config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "copilot_chats_user_id_idx": { - "name": "copilot_chats_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "copilot_chats_workflow_id_idx": { - "name": "copilot_chats_workflow_id_idx", - "columns": [ - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "copilot_chats_user_workflow_idx": { - "name": "copilot_chats_user_workflow_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "copilot_chats_created_at_idx": { - "name": "copilot_chats_created_at_idx", - "columns": [ - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "copilot_chats_updated_at_idx": { - "name": "copilot_chats_updated_at_idx", - "columns": [ - { - "expression": "updated_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "copilot_chats_user_id_user_id_fk": { - "name": "copilot_chats_user_id_user_id_fk", - "tableFrom": "copilot_chats", - "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "copilot_chats_workflow_id_workflow_id_fk": { - "name": "copilot_chats_workflow_id_workflow_id_fk", - "tableFrom": "copilot_chats", - "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.copilot_feedback": { - "name": "copilot_feedback", - "schema": "", - "columns": { - "feedback_id": { - "name": "feedback_id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "chat_id": { - "name": "chat_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "user_query": { - "name": "user_query", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "agent_response": { - "name": "agent_response", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "is_positive": { - "name": "is_positive", - "type": "boolean", - "primaryKey": false, - "notNull": true - }, - "feedback": { - "name": "feedback", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "workflow_yaml": { - "name": "workflow_yaml", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "copilot_feedback_user_id_idx": { - "name": "copilot_feedback_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "copilot_feedback_chat_id_idx": { - "name": "copilot_feedback_chat_id_idx", - "columns": [ - { - "expression": "chat_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "copilot_feedback_user_chat_idx": { - "name": "copilot_feedback_user_chat_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "chat_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "copilot_feedback_is_positive_idx": { - "name": "copilot_feedback_is_positive_idx", - "columns": [ - { - "expression": "is_positive", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "copilot_feedback_created_at_idx": { - "name": "copilot_feedback_created_at_idx", - "columns": [ - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "copilot_feedback_user_id_user_id_fk": { - "name": "copilot_feedback_user_id_user_id_fk", - "tableFrom": "copilot_feedback", - "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "copilot_feedback_chat_id_copilot_chats_id_fk": { - "name": "copilot_feedback_chat_id_copilot_chats_id_fk", - "tableFrom": "copilot_feedback", - "tableTo": "copilot_chats", - "columnsFrom": ["chat_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.custom_tools": { - "name": "custom_tools", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "workspace_id": { - "name": "workspace_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "title": { - "name": "title", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "schema": { - "name": "schema", - "type": "json", - "primaryKey": false, - "notNull": true - }, - "code": { - "name": "code", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "custom_tools_workspace_id_idx": { - "name": "custom_tools_workspace_id_idx", - "columns": [ - { - "expression": "workspace_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "custom_tools_workspace_title_unique": { - "name": "custom_tools_workspace_title_unique", - "columns": [ - { - "expression": "workspace_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "title", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "custom_tools_workspace_id_workspace_id_fk": { - "name": "custom_tools_workspace_id_workspace_id_fk", - "tableFrom": "custom_tools", - "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "custom_tools_user_id_user_id_fk": { - "name": "custom_tools_user_id_user_id_fk", - "tableFrom": "custom_tools", - "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.docs_embeddings": { - "name": "docs_embeddings", - "schema": "", - "columns": { - "chunk_id": { - "name": "chunk_id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "chunk_text": { - "name": "chunk_text", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "source_document": { - "name": "source_document", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "source_link": { - "name": "source_link", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "header_text": { - "name": "header_text", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "header_level": { - "name": "header_level", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "token_count": { - "name": "token_count", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "embedding": { - "name": "embedding", - "type": "vector(1536)", - "primaryKey": false, - "notNull": true - }, - "embedding_model": { - "name": "embedding_model", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'text-embedding-3-small'" - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": true, - "default": "'{}'" - }, - "chunk_text_tsv": { - "name": "chunk_text_tsv", - "type": "tsvector", - "primaryKey": false, - "notNull": false, - "generated": { - "as": "to_tsvector('english', \"docs_embeddings\".\"chunk_text\")", - "type": "stored" - } - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "docs_emb_source_document_idx": { - "name": "docs_emb_source_document_idx", - "columns": [ - { - "expression": "source_document", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "docs_emb_header_level_idx": { - "name": "docs_emb_header_level_idx", - "columns": [ - { - "expression": "header_level", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "docs_emb_source_header_idx": { - "name": "docs_emb_source_header_idx", - "columns": [ - { - "expression": "source_document", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "header_level", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "docs_emb_model_idx": { - "name": "docs_emb_model_idx", - "columns": [ - { - "expression": "embedding_model", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "docs_emb_created_at_idx": { - "name": "docs_emb_created_at_idx", - "columns": [ - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "docs_embedding_vector_hnsw_idx": { - "name": "docs_embedding_vector_hnsw_idx", - "columns": [ - { - "expression": "embedding", - "isExpression": false, - "asc": true, - "nulls": "last", - "opclass": "vector_cosine_ops" - } - ], - "isUnique": false, - "concurrently": false, - "method": "hnsw", - "with": { - "m": 16, - "ef_construction": 64 - } - }, - "docs_emb_metadata_gin_idx": { - "name": "docs_emb_metadata_gin_idx", - "columns": [ - { - "expression": "metadata", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "gin", - "with": {} - }, - "docs_emb_chunk_text_fts_idx": { - "name": "docs_emb_chunk_text_fts_idx", - "columns": [ - { - "expression": "chunk_text_tsv", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "gin", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": { - "docs_embedding_not_null_check": { - "name": "docs_embedding_not_null_check", - "value": "\"embedding\" IS NOT NULL" - }, - "docs_header_level_check": { - "name": "docs_header_level_check", - "value": "\"header_level\" >= 1 AND \"header_level\" <= 6" - } - }, - "isRLSEnabled": false - }, - "public.document": { - "name": "document", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "knowledge_base_id": { - "name": "knowledge_base_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "filename": { - "name": "filename", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "file_url": { - "name": "file_url", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "file_size": { - "name": "file_size", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "mime_type": { - "name": "mime_type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "chunk_count": { - "name": "chunk_count", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "token_count": { - "name": "token_count", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "character_count": { - "name": "character_count", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "processing_status": { - "name": "processing_status", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'pending'" - }, - "processing_started_at": { - "name": "processing_started_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "processing_completed_at": { - "name": "processing_completed_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "processing_error": { - "name": "processing_error", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "enabled": { - "name": "enabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "deleted_at": { - "name": "deleted_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "tag1": { - "name": "tag1", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "tag2": { - "name": "tag2", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "tag3": { - "name": "tag3", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "tag4": { - "name": "tag4", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "tag5": { - "name": "tag5", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "tag6": { - "name": "tag6", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "tag7": { - "name": "tag7", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "uploaded_at": { - "name": "uploaded_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "doc_kb_id_idx": { - "name": "doc_kb_id_idx", - "columns": [ - { - "expression": "knowledge_base_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "doc_filename_idx": { - "name": "doc_filename_idx", - "columns": [ - { - "expression": "filename", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "doc_processing_status_idx": { - "name": "doc_processing_status_idx", - "columns": [ - { - "expression": "knowledge_base_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "processing_status", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "doc_tag1_idx": { - "name": "doc_tag1_idx", - "columns": [ - { - "expression": "tag1", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "doc_tag2_idx": { - "name": "doc_tag2_idx", - "columns": [ - { - "expression": "tag2", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "doc_tag3_idx": { - "name": "doc_tag3_idx", - "columns": [ - { - "expression": "tag3", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "doc_tag4_idx": { - "name": "doc_tag4_idx", - "columns": [ - { - "expression": "tag4", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "doc_tag5_idx": { - "name": "doc_tag5_idx", - "columns": [ - { - "expression": "tag5", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "doc_tag6_idx": { - "name": "doc_tag6_idx", - "columns": [ - { - "expression": "tag6", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "doc_tag7_idx": { - "name": "doc_tag7_idx", - "columns": [ - { - "expression": "tag7", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "document_knowledge_base_id_knowledge_base_id_fk": { - "name": "document_knowledge_base_id_knowledge_base_id_fk", - "tableFrom": "document", - "tableTo": "knowledge_base", - "columnsFrom": ["knowledge_base_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.embedding": { - "name": "embedding", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "knowledge_base_id": { - "name": "knowledge_base_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "document_id": { - "name": "document_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "chunk_index": { - "name": "chunk_index", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "chunk_hash": { - "name": "chunk_hash", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "content": { - "name": "content", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "content_length": { - "name": "content_length", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "token_count": { - "name": "token_count", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "embedding": { - "name": "embedding", - "type": "vector(1536)", - "primaryKey": false, - "notNull": false - }, - "embedding_model": { - "name": "embedding_model", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'text-embedding-3-small'" - }, - "start_offset": { - "name": "start_offset", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "end_offset": { - "name": "end_offset", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "tag1": { - "name": "tag1", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "tag2": { - "name": "tag2", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "tag3": { - "name": "tag3", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "tag4": { - "name": "tag4", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "tag5": { - "name": "tag5", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "tag6": { - "name": "tag6", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "tag7": { - "name": "tag7", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "enabled": { - "name": "enabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "content_tsv": { - "name": "content_tsv", - "type": "tsvector", - "primaryKey": false, - "notNull": false, - "generated": { - "as": "to_tsvector('english', \"embedding\".\"content\")", - "type": "stored" - } - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "emb_kb_id_idx": { - "name": "emb_kb_id_idx", - "columns": [ - { - "expression": "knowledge_base_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "emb_doc_id_idx": { - "name": "emb_doc_id_idx", - "columns": [ - { - "expression": "document_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "emb_doc_chunk_idx": { - "name": "emb_doc_chunk_idx", - "columns": [ - { - "expression": "document_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "chunk_index", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - }, - "emb_kb_model_idx": { - "name": "emb_kb_model_idx", - "columns": [ - { - "expression": "knowledge_base_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "embedding_model", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "emb_kb_enabled_idx": { - "name": "emb_kb_enabled_idx", - "columns": [ - { - "expression": "knowledge_base_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "enabled", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "emb_doc_enabled_idx": { - "name": "emb_doc_enabled_idx", - "columns": [ - { - "expression": "document_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "enabled", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "embedding_vector_hnsw_idx": { - "name": "embedding_vector_hnsw_idx", - "columns": [ - { - "expression": "embedding", - "isExpression": false, - "asc": true, - "nulls": "last", - "opclass": "vector_cosine_ops" - } - ], - "isUnique": false, - "concurrently": false, - "method": "hnsw", - "with": { - "m": 16, - "ef_construction": 64 - } - }, - "emb_tag1_idx": { - "name": "emb_tag1_idx", - "columns": [ - { - "expression": "tag1", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "emb_tag2_idx": { - "name": "emb_tag2_idx", - "columns": [ - { - "expression": "tag2", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "emb_tag3_idx": { - "name": "emb_tag3_idx", - "columns": [ - { - "expression": "tag3", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "emb_tag4_idx": { - "name": "emb_tag4_idx", - "columns": [ - { - "expression": "tag4", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "emb_tag5_idx": { - "name": "emb_tag5_idx", - "columns": [ - { - "expression": "tag5", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "emb_tag6_idx": { - "name": "emb_tag6_idx", - "columns": [ - { - "expression": "tag6", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "emb_tag7_idx": { - "name": "emb_tag7_idx", - "columns": [ - { - "expression": "tag7", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "emb_content_fts_idx": { - "name": "emb_content_fts_idx", - "columns": [ - { - "expression": "content_tsv", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "gin", - "with": {} - } - }, - "foreignKeys": { - "embedding_knowledge_base_id_knowledge_base_id_fk": { - "name": "embedding_knowledge_base_id_knowledge_base_id_fk", - "tableFrom": "embedding", - "tableTo": "knowledge_base", - "columnsFrom": ["knowledge_base_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "embedding_document_id_document_id_fk": { - "name": "embedding_document_id_document_id_fk", - "tableFrom": "embedding", - "tableTo": "document", - "columnsFrom": ["document_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": { - "embedding_not_null_check": { - "name": "embedding_not_null_check", - "value": "\"embedding\" IS NOT NULL" - } - }, - "isRLSEnabled": false - }, - "public.environment": { - "name": "environment", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "variables": { - "name": "variables", - "type": "json", - "primaryKey": false, - "notNull": true - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "environment_user_id_user_id_fk": { - "name": "environment_user_id_user_id_fk", - "tableFrom": "environment", - "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "environment_user_id_unique": { - "name": "environment_user_id_unique", - "nullsNotDistinct": false, - "columns": ["user_id"] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.idempotency_key": { - "name": "idempotency_key", - "schema": "", - "columns": { - "key": { - "name": "key", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "namespace": { - "name": "namespace", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'default'" - }, - "result": { - "name": "result", - "type": "json", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "idempotency_key_namespace_unique": { - "name": "idempotency_key_namespace_unique", - "columns": [ - { - "expression": "key", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "namespace", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idempotency_key_created_at_idx": { - "name": "idempotency_key_created_at_idx", - "columns": [ - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idempotency_key_namespace_idx": { - "name": "idempotency_key_namespace_idx", - "columns": [ - { - "expression": "namespace", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.invitation": { - "name": "invitation", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "email": { - "name": "email", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "inviter_id": { - "name": "inviter_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "organization_id": { - "name": "organization_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "role": { - "name": "role", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "invitation_email_idx": { - "name": "invitation_email_idx", - "columns": [ - { - "expression": "email", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "invitation_organization_id_idx": { - "name": "invitation_organization_id_idx", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "invitation_inviter_id_user_id_fk": { - "name": "invitation_inviter_id_user_id_fk", - "tableFrom": "invitation", - "tableTo": "user", - "columnsFrom": ["inviter_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "invitation_organization_id_organization_id_fk": { - "name": "invitation_organization_id_organization_id_fk", - "tableFrom": "invitation", - "tableTo": "organization", - "columnsFrom": ["organization_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.knowledge_base": { - "name": "knowledge_base", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "workspace_id": { - "name": "workspace_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "token_count": { - "name": "token_count", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "embedding_model": { - "name": "embedding_model", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'text-embedding-3-small'" - }, - "embedding_dimension": { - "name": "embedding_dimension", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 1536 - }, - "chunking_config": { - "name": "chunking_config", - "type": "json", - "primaryKey": false, - "notNull": true, - "default": "'{\"maxSize\": 1024, \"minSize\": 1, \"overlap\": 200}'" - }, - "deleted_at": { - "name": "deleted_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "kb_user_id_idx": { - "name": "kb_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "kb_workspace_id_idx": { - "name": "kb_workspace_id_idx", - "columns": [ - { - "expression": "workspace_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "kb_user_workspace_idx": { - "name": "kb_user_workspace_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "workspace_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "kb_deleted_at_idx": { - "name": "kb_deleted_at_idx", - "columns": [ - { - "expression": "deleted_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "knowledge_base_user_id_user_id_fk": { - "name": "knowledge_base_user_id_user_id_fk", - "tableFrom": "knowledge_base", - "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "knowledge_base_workspace_id_workspace_id_fk": { - "name": "knowledge_base_workspace_id_workspace_id_fk", - "tableFrom": "knowledge_base", - "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.knowledge_base_tag_definitions": { - "name": "knowledge_base_tag_definitions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "knowledge_base_id": { - "name": "knowledge_base_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "tag_slot": { - "name": "tag_slot", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "display_name": { - "name": "display_name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "field_type": { - "name": "field_type", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'text'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "kb_tag_definitions_kb_slot_idx": { - "name": "kb_tag_definitions_kb_slot_idx", - "columns": [ - { - "expression": "knowledge_base_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "tag_slot", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - }, - "kb_tag_definitions_kb_display_name_idx": { - "name": "kb_tag_definitions_kb_display_name_idx", - "columns": [ - { - "expression": "knowledge_base_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "display_name", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - }, - "kb_tag_definitions_kb_id_idx": { - "name": "kb_tag_definitions_kb_id_idx", - "columns": [ - { - "expression": "knowledge_base_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "knowledge_base_tag_definitions_knowledge_base_id_knowledge_base_id_fk": { - "name": "knowledge_base_tag_definitions_knowledge_base_id_knowledge_base_id_fk", - "tableFrom": "knowledge_base_tag_definitions", - "tableTo": "knowledge_base", - "columnsFrom": ["knowledge_base_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.mcp_servers": { - "name": "mcp_servers", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "workspace_id": { - "name": "workspace_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_by": { - "name": "created_by", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "transport": { - "name": "transport", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "url": { - "name": "url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "headers": { - "name": "headers", - "type": "json", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "timeout": { - "name": "timeout", - "type": "integer", - "primaryKey": false, - "notNull": false, - "default": 30000 - }, - "retries": { - "name": "retries", - "type": "integer", - "primaryKey": false, - "notNull": false, - "default": 3 - }, - "enabled": { - "name": "enabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "last_connected": { - "name": "last_connected", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "connection_status": { - "name": "connection_status", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'disconnected'" - }, - "last_error": { - "name": "last_error", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "tool_count": { - "name": "tool_count", - "type": "integer", - "primaryKey": false, - "notNull": false, - "default": 0 - }, - "last_tools_refresh": { - "name": "last_tools_refresh", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "total_requests": { - "name": "total_requests", - "type": "integer", - "primaryKey": false, - "notNull": false, - "default": 0 - }, - "last_used": { - "name": "last_used", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "deleted_at": { - "name": "deleted_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "mcp_servers_workspace_enabled_idx": { - "name": "mcp_servers_workspace_enabled_idx", - "columns": [ - { - "expression": "workspace_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "enabled", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "mcp_servers_workspace_deleted_idx": { - "name": "mcp_servers_workspace_deleted_idx", - "columns": [ - { - "expression": "workspace_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "deleted_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "mcp_servers_workspace_id_workspace_id_fk": { - "name": "mcp_servers_workspace_id_workspace_id_fk", - "tableFrom": "mcp_servers", - "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "mcp_servers_created_by_user_id_fk": { - "name": "mcp_servers_created_by_user_id_fk", - "tableFrom": "mcp_servers", - "tableTo": "user", - "columnsFrom": ["created_by"], - "columnsTo": ["id"], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.member": { - "name": "member", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "organization_id": { - "name": "organization_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "role": { - "name": "role", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "member_user_id_idx": { - "name": "member_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "member_organization_id_idx": { - "name": "member_organization_id_idx", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "member_user_id_user_id_fk": { - "name": "member_user_id_user_id_fk", - "tableFrom": "member", - "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "member_organization_id_organization_id_fk": { - "name": "member_organization_id_organization_id_fk", - "tableFrom": "member", - "tableTo": "organization", - "columnsFrom": ["organization_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.memory": { - "name": "memory", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "workflow_id": { - "name": "workflow_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "key": { - "name": "key", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "data": { - "name": "data", - "type": "jsonb", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "deleted_at": { - "name": "deleted_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "memory_key_idx": { - "name": "memory_key_idx", - "columns": [ - { - "expression": "key", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "memory_workflow_idx": { - "name": "memory_workflow_idx", - "columns": [ - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "memory_workflow_key_idx": { - "name": "memory_workflow_key_idx", - "columns": [ - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "key", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "memory_workflow_id_workflow_id_fk": { - "name": "memory_workflow_id_workflow_id_fk", - "tableFrom": "memory", - "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.organization": { - "name": "organization", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "logo": { - "name": "logo", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "metadata": { - "name": "metadata", - "type": "json", - "primaryKey": false, - "notNull": false - }, - "org_usage_limit": { - "name": "org_usage_limit", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "storage_used_bytes": { - "name": "storage_used_bytes", - "type": "bigint", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "departed_member_usage": { - "name": "departed_member_usage", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "'0'" - }, - "credit_balance": { - "name": "credit_balance", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "'0'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.paused_executions": { - "name": "paused_executions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "workflow_id": { - "name": "workflow_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "execution_id": { - "name": "execution_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "execution_snapshot": { - "name": "execution_snapshot", - "type": "jsonb", - "primaryKey": false, - "notNull": true - }, - "pause_points": { - "name": "pause_points", - "type": "jsonb", - "primaryKey": false, - "notNull": true - }, - "total_pause_count": { - "name": "total_pause_count", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "resumed_count": { - "name": "resumed_count", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'paused'" - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": true, - "default": "'{}'::jsonb" - }, - "paused_at": { - "name": "paused_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "paused_executions_workflow_id_idx": { - "name": "paused_executions_workflow_id_idx", - "columns": [ - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "paused_executions_status_idx": { - "name": "paused_executions_status_idx", - "columns": [ - { - "expression": "status", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "paused_executions_execution_id_unique": { - "name": "paused_executions_execution_id_unique", - "columns": [ - { - "expression": "execution_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "paused_executions_workflow_id_workflow_id_fk": { - "name": "paused_executions_workflow_id_workflow_id_fk", - "tableFrom": "paused_executions", - "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.permissions": { - "name": "permissions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "entity_type": { - "name": "entity_type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "entity_id": { - "name": "entity_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "permission_type": { - "name": "permission_type", - "type": "permission_type", - "typeSchema": "public", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "permissions_user_id_idx": { - "name": "permissions_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "permissions_entity_idx": { - "name": "permissions_entity_idx", - "columns": [ - { - "expression": "entity_type", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "entity_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "permissions_user_entity_type_idx": { - "name": "permissions_user_entity_type_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "entity_type", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "permissions_user_entity_permission_idx": { - "name": "permissions_user_entity_permission_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "entity_type", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "permission_type", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "permissions_user_entity_idx": { - "name": "permissions_user_entity_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "entity_type", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "entity_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "permissions_unique_constraint": { - "name": "permissions_unique_constraint", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "entity_type", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "entity_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "permissions_user_id_user_id_fk": { - "name": "permissions_user_id_user_id_fk", - "tableFrom": "permissions", - "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.rate_limit_bucket": { - "name": "rate_limit_bucket", - "schema": "", - "columns": { - "key": { - "name": "key", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "tokens": { - "name": "tokens", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "last_refill_at": { - "name": "last_refill_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.resume_queue": { - "name": "resume_queue", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "paused_execution_id": { - "name": "paused_execution_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "parent_execution_id": { - "name": "parent_execution_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "new_execution_id": { - "name": "new_execution_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "context_id": { - "name": "context_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "resume_input": { - "name": "resume_input", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'pending'" - }, - "queued_at": { - "name": "queued_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "claimed_at": { - "name": "claimed_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "completed_at": { - "name": "completed_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "failure_reason": { - "name": "failure_reason", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "resume_queue_parent_status_idx": { - "name": "resume_queue_parent_status_idx", - "columns": [ - { - "expression": "parent_execution_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "status", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "queued_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "resume_queue_new_execution_idx": { - "name": "resume_queue_new_execution_idx", - "columns": [ - { - "expression": "new_execution_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "resume_queue_paused_execution_id_paused_executions_id_fk": { - "name": "resume_queue_paused_execution_id_paused_executions_id_fk", - "tableFrom": "resume_queue", - "tableTo": "paused_executions", - "columnsFrom": ["paused_execution_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.session": { - "name": "session", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "token": { - "name": "token", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "ip_address": { - "name": "ip_address", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_agent": { - "name": "user_agent", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "active_organization_id": { - "name": "active_organization_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "session_user_id_idx": { - "name": "session_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "session_token_idx": { - "name": "session_token_idx", - "columns": [ - { - "expression": "token", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "session_user_id_user_id_fk": { - "name": "session_user_id_user_id_fk", - "tableFrom": "session", - "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "session_active_organization_id_organization_id_fk": { - "name": "session_active_organization_id_organization_id_fk", - "tableFrom": "session", - "tableTo": "organization", - "columnsFrom": ["active_organization_id"], - "columnsTo": ["id"], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "session_token_unique": { - "name": "session_token_unique", - "nullsNotDistinct": false, - "columns": ["token"] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.settings": { - "name": "settings", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "theme": { - "name": "theme", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'system'" - }, - "auto_connect": { - "name": "auto_connect", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "telemetry_enabled": { - "name": "telemetry_enabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "email_preferences": { - "name": "email_preferences", - "type": "json", - "primaryKey": false, - "notNull": true, - "default": "'{}'" - }, - "billing_usage_notifications_enabled": { - "name": "billing_usage_notifications_enabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "show_training_controls": { - "name": "show_training_controls", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "super_user_mode_enabled": { - "name": "super_user_mode_enabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "error_notifications_enabled": { - "name": "error_notifications_enabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "copilot_enabled_models": { - "name": "copilot_enabled_models", - "type": "jsonb", - "primaryKey": false, - "notNull": true, - "default": "'{}'" - }, - "copilot_auto_allowed_tools": { - "name": "copilot_auto_allowed_tools", - "type": "jsonb", - "primaryKey": false, - "notNull": true, - "default": "'[]'" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "settings_user_id_user_id_fk": { - "name": "settings_user_id_user_id_fk", - "tableFrom": "settings", - "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "settings_user_id_unique": { - "name": "settings_user_id_unique", - "nullsNotDistinct": false, - "columns": ["user_id"] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.sso_provider": { - "name": "sso_provider", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "issuer": { - "name": "issuer", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "domain": { - "name": "domain", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "oidc_config": { - "name": "oidc_config", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "saml_config": { - "name": "saml_config", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "provider_id": { - "name": "provider_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "organization_id": { - "name": "organization_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "sso_provider_provider_id_idx": { - "name": "sso_provider_provider_id_idx", - "columns": [ - { - "expression": "provider_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "sso_provider_domain_idx": { - "name": "sso_provider_domain_idx", - "columns": [ - { - "expression": "domain", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "sso_provider_user_id_idx": { - "name": "sso_provider_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "sso_provider_organization_id_idx": { - "name": "sso_provider_organization_id_idx", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "sso_provider_user_id_user_id_fk": { - "name": "sso_provider_user_id_user_id_fk", - "tableFrom": "sso_provider", - "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "sso_provider_organization_id_organization_id_fk": { - "name": "sso_provider_organization_id_organization_id_fk", - "tableFrom": "sso_provider", - "tableTo": "organization", - "columnsFrom": ["organization_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.subscription": { - "name": "subscription", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "plan": { - "name": "plan", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "reference_id": { - "name": "reference_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "stripe_customer_id": { - "name": "stripe_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "stripe_subscription_id": { - "name": "stripe_subscription_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "period_start": { - "name": "period_start", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "period_end": { - "name": "period_end", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "cancel_at_period_end": { - "name": "cancel_at_period_end", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "seats": { - "name": "seats", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "trial_start": { - "name": "trial_start", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "trial_end": { - "name": "trial_end", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "metadata": { - "name": "metadata", - "type": "json", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "subscription_reference_status_idx": { - "name": "subscription_reference_status_idx", - "columns": [ - { - "expression": "reference_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "status", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": { - "check_enterprise_metadata": { - "name": "check_enterprise_metadata", - "value": "plan != 'enterprise' OR metadata IS NOT NULL" - } - }, - "isRLSEnabled": false - }, - "public.template_creators": { - "name": "template_creators", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "reference_type": { - "name": "reference_type", - "type": "template_creator_type", - "typeSchema": "public", - "primaryKey": false, - "notNull": true - }, - "reference_id": { - "name": "reference_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "profile_image_url": { - "name": "profile_image_url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "details": { - "name": "details", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "verified": { - "name": "verified", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "created_by": { - "name": "created_by", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "template_creators_reference_idx": { - "name": "template_creators_reference_idx", - "columns": [ - { - "expression": "reference_type", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "reference_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - }, - "template_creators_reference_id_idx": { - "name": "template_creators_reference_id_idx", - "columns": [ - { - "expression": "reference_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "template_creators_created_by_idx": { - "name": "template_creators_created_by_idx", - "columns": [ - { - "expression": "created_by", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "template_creators_created_by_user_id_fk": { - "name": "template_creators_created_by_user_id_fk", - "tableFrom": "template_creators", - "tableTo": "user", - "columnsFrom": ["created_by"], - "columnsTo": ["id"], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.template_stars": { - "name": "template_stars", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "template_id": { - "name": "template_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "starred_at": { - "name": "starred_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "template_stars_user_id_idx": { - "name": "template_stars_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "template_stars_template_id_idx": { - "name": "template_stars_template_id_idx", - "columns": [ - { - "expression": "template_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "template_stars_user_template_idx": { - "name": "template_stars_user_template_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "template_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "template_stars_template_user_idx": { - "name": "template_stars_template_user_idx", - "columns": [ - { - "expression": "template_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "template_stars_starred_at_idx": { - "name": "template_stars_starred_at_idx", - "columns": [ - { - "expression": "starred_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "template_stars_template_starred_at_idx": { - "name": "template_stars_template_starred_at_idx", - "columns": [ - { - "expression": "template_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "starred_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "template_stars_user_template_unique": { - "name": "template_stars_user_template_unique", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "template_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "template_stars_user_id_user_id_fk": { - "name": "template_stars_user_id_user_id_fk", - "tableFrom": "template_stars", - "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "template_stars_template_id_templates_id_fk": { - "name": "template_stars_template_id_templates_id_fk", - "tableFrom": "template_stars", - "tableTo": "templates", - "columnsFrom": ["template_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.templates": { - "name": "templates", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "workflow_id": { - "name": "workflow_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "details": { - "name": "details", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "creator_id": { - "name": "creator_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "views": { - "name": "views", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "stars": { - "name": "stars", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "status": { - "name": "status", - "type": "template_status", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'pending'" - }, - "tags": { - "name": "tags", - "type": "text[]", - "primaryKey": false, - "notNull": true, - "default": "'{}'::text[]" - }, - "required_credentials": { - "name": "required_credentials", - "type": "jsonb", - "primaryKey": false, - "notNull": true, - "default": "'[]'" - }, - "state": { - "name": "state", - "type": "jsonb", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "templates_status_idx": { - "name": "templates_status_idx", - "columns": [ - { - "expression": "status", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "templates_creator_id_idx": { - "name": "templates_creator_id_idx", - "columns": [ - { - "expression": "creator_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "templates_views_idx": { - "name": "templates_views_idx", - "columns": [ - { - "expression": "views", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "templates_stars_idx": { - "name": "templates_stars_idx", - "columns": [ - { - "expression": "stars", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "templates_status_views_idx": { - "name": "templates_status_views_idx", - "columns": [ - { - "expression": "status", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "views", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "templates_status_stars_idx": { - "name": "templates_status_stars_idx", - "columns": [ - { - "expression": "status", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "stars", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "templates_created_at_idx": { - "name": "templates_created_at_idx", - "columns": [ - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "templates_updated_at_idx": { - "name": "templates_updated_at_idx", - "columns": [ - { - "expression": "updated_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "templates_workflow_id_workflow_id_fk": { - "name": "templates_workflow_id_workflow_id_fk", - "tableFrom": "templates", - "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], - "onDelete": "set null", - "onUpdate": "no action" - }, - "templates_creator_id_template_creators_id_fk": { - "name": "templates_creator_id_template_creators_id_fk", - "tableFrom": "templates", - "tableTo": "template_creators", - "columnsFrom": ["creator_id"], - "columnsTo": ["id"], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.user": { - "name": "user", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "email": { - "name": "email", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "email_verified": { - "name": "email_verified", - "type": "boolean", - "primaryKey": false, - "notNull": true - }, - "image": { - "name": "image", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "stripe_customer_id": { - "name": "stripe_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "is_super_user": { - "name": "is_super_user", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "user_email_unique": { - "name": "user_email_unique", - "nullsNotDistinct": false, - "columns": ["email"] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.user_stats": { - "name": "user_stats", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "total_manual_executions": { - "name": "total_manual_executions", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "total_api_calls": { - "name": "total_api_calls", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "total_webhook_triggers": { - "name": "total_webhook_triggers", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "total_scheduled_executions": { - "name": "total_scheduled_executions", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "total_chat_executions": { - "name": "total_chat_executions", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "total_tokens_used": { - "name": "total_tokens_used", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "total_cost": { - "name": "total_cost", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "'0'" - }, - "current_usage_limit": { - "name": "current_usage_limit", - "type": "numeric", - "primaryKey": false, - "notNull": false, - "default": "'10'" - }, - "usage_limit_updated_at": { - "name": "usage_limit_updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false, - "default": "now()" - }, - "current_period_cost": { - "name": "current_period_cost", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "'0'" - }, - "last_period_cost": { - "name": "last_period_cost", - "type": "numeric", - "primaryKey": false, - "notNull": false, - "default": "'0'" - }, - "billed_overage_this_period": { - "name": "billed_overage_this_period", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "'0'" - }, - "pro_period_cost_snapshot": { - "name": "pro_period_cost_snapshot", - "type": "numeric", - "primaryKey": false, - "notNull": false, - "default": "'0'" - }, - "credit_balance": { - "name": "credit_balance", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "'0'" - }, - "total_copilot_cost": { - "name": "total_copilot_cost", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "'0'" - }, - "current_period_copilot_cost": { - "name": "current_period_copilot_cost", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "'0'" - }, - "last_period_copilot_cost": { - "name": "last_period_copilot_cost", - "type": "numeric", - "primaryKey": false, - "notNull": false, - "default": "'0'" - }, - "total_copilot_tokens": { - "name": "total_copilot_tokens", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "total_copilot_calls": { - "name": "total_copilot_calls", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "storage_used_bytes": { - "name": "storage_used_bytes", - "type": "bigint", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "last_active": { - "name": "last_active", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "billing_blocked": { - "name": "billing_blocked", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "billing_blocked_reason": { - "name": "billing_blocked_reason", - "type": "billing_blocked_reason", - "typeSchema": "public", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "user_stats_user_id_user_id_fk": { - "name": "user_stats_user_id_user_id_fk", - "tableFrom": "user_stats", - "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "user_stats_user_id_unique": { - "name": "user_stats_user_id_unique", - "nullsNotDistinct": false, - "columns": ["user_id"] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.verification": { - "name": "verification", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "identifier": { - "name": "identifier", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "value": { - "name": "value", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "verification_identifier_idx": { - "name": "verification_identifier_idx", - "columns": [ - { - "expression": "identifier", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.waitlist": { - "name": "waitlist", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "email": { - "name": "email", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'pending'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "waitlist_email_unique": { - "name": "waitlist_email_unique", - "nullsNotDistinct": false, - "columns": ["email"] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.webhook": { - "name": "webhook", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "workflow_id": { - "name": "workflow_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "block_id": { - "name": "block_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "path": { - "name": "path", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "provider": { - "name": "provider", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "provider_config": { - "name": "provider_config", - "type": "json", - "primaryKey": false, - "notNull": false - }, - "is_active": { - "name": "is_active", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "failed_count": { - "name": "failed_count", - "type": "integer", - "primaryKey": false, - "notNull": false, - "default": 0 - }, - "last_failed_at": { - "name": "last_failed_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "path_idx": { - "name": "path_idx", - "columns": [ - { - "expression": "path", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_webhook_on_workflow_id_block_id": { - "name": "idx_webhook_on_workflow_id_block_id", - "columns": [ - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "block_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "webhook_workflow_id_workflow_id_fk": { - "name": "webhook_workflow_id_workflow_id_fk", - "tableFrom": "webhook", - "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "webhook_block_id_workflow_blocks_id_fk": { - "name": "webhook_block_id_workflow_blocks_id_fk", - "tableFrom": "webhook", - "tableTo": "workflow_blocks", - "columnsFrom": ["block_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.workflow": { - "name": "workflow", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "workspace_id": { - "name": "workspace_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "folder_id": { - "name": "folder_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "color": { - "name": "color", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'#3972F6'" - }, - "last_synced": { - "name": "last_synced", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "is_deployed": { - "name": "is_deployed", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "deployed_at": { - "name": "deployed_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "run_count": { - "name": "run_count", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "last_run_at": { - "name": "last_run_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "variables": { - "name": "variables", - "type": "json", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - } - }, - "indexes": { - "workflow_user_id_idx": { - "name": "workflow_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_workspace_id_idx": { - "name": "workflow_workspace_id_idx", - "columns": [ - { - "expression": "workspace_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_user_workspace_idx": { - "name": "workflow_user_workspace_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "workspace_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "workflow_user_id_user_id_fk": { - "name": "workflow_user_id_user_id_fk", - "tableFrom": "workflow", - "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "workflow_workspace_id_workspace_id_fk": { - "name": "workflow_workspace_id_workspace_id_fk", - "tableFrom": "workflow", - "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "workflow_folder_id_workflow_folder_id_fk": { - "name": "workflow_folder_id_workflow_folder_id_fk", - "tableFrom": "workflow", - "tableTo": "workflow_folder", - "columnsFrom": ["folder_id"], - "columnsTo": ["id"], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.workflow_blocks": { - "name": "workflow_blocks", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "workflow_id": { - "name": "workflow_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "position_x": { - "name": "position_x", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "position_y": { - "name": "position_y", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "enabled": { - "name": "enabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "horizontal_handles": { - "name": "horizontal_handles", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "is_wide": { - "name": "is_wide", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "advanced_mode": { - "name": "advanced_mode", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "trigger_mode": { - "name": "trigger_mode", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "height": { - "name": "height", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "'0'" - }, - "sub_blocks": { - "name": "sub_blocks", - "type": "jsonb", - "primaryKey": false, - "notNull": true, - "default": "'{}'" - }, - "outputs": { - "name": "outputs", - "type": "jsonb", - "primaryKey": false, - "notNull": true, - "default": "'{}'" - }, - "data": { - "name": "data", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "workflow_blocks_workflow_id_idx": { - "name": "workflow_blocks_workflow_id_idx", - "columns": [ - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "workflow_blocks_workflow_id_workflow_id_fk": { - "name": "workflow_blocks_workflow_id_workflow_id_fk", - "tableFrom": "workflow_blocks", - "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.workflow_checkpoints": { - "name": "workflow_checkpoints", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "workflow_id": { - "name": "workflow_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "chat_id": { - "name": "chat_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "message_id": { - "name": "message_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "workflow_state": { - "name": "workflow_state", - "type": "json", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "workflow_checkpoints_user_id_idx": { - "name": "workflow_checkpoints_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_checkpoints_workflow_id_idx": { - "name": "workflow_checkpoints_workflow_id_idx", - "columns": [ - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_checkpoints_chat_id_idx": { - "name": "workflow_checkpoints_chat_id_idx", - "columns": [ - { - "expression": "chat_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_checkpoints_message_id_idx": { - "name": "workflow_checkpoints_message_id_idx", - "columns": [ - { - "expression": "message_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_checkpoints_user_workflow_idx": { - "name": "workflow_checkpoints_user_workflow_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_checkpoints_workflow_chat_idx": { - "name": "workflow_checkpoints_workflow_chat_idx", - "columns": [ - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "chat_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_checkpoints_created_at_idx": { - "name": "workflow_checkpoints_created_at_idx", - "columns": [ - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_checkpoints_chat_created_at_idx": { - "name": "workflow_checkpoints_chat_created_at_idx", - "columns": [ - { - "expression": "chat_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "workflow_checkpoints_user_id_user_id_fk": { - "name": "workflow_checkpoints_user_id_user_id_fk", - "tableFrom": "workflow_checkpoints", - "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "workflow_checkpoints_workflow_id_workflow_id_fk": { - "name": "workflow_checkpoints_workflow_id_workflow_id_fk", - "tableFrom": "workflow_checkpoints", - "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "workflow_checkpoints_chat_id_copilot_chats_id_fk": { - "name": "workflow_checkpoints_chat_id_copilot_chats_id_fk", - "tableFrom": "workflow_checkpoints", - "tableTo": "copilot_chats", - "columnsFrom": ["chat_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.workflow_deployment_version": { - "name": "workflow_deployment_version", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "workflow_id": { - "name": "workflow_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "version": { - "name": "version", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "state": { - "name": "state", - "type": "json", - "primaryKey": false, - "notNull": true - }, - "is_active": { - "name": "is_active", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "created_by": { - "name": "created_by", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "workflow_deployment_version_workflow_version_unique": { - "name": "workflow_deployment_version_workflow_version_unique", - "columns": [ - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "version", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_deployment_version_workflow_active_idx": { - "name": "workflow_deployment_version_workflow_active_idx", - "columns": [ - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "is_active", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_deployment_version_created_at_idx": { - "name": "workflow_deployment_version_created_at_idx", - "columns": [ - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "workflow_deployment_version_workflow_id_workflow_id_fk": { - "name": "workflow_deployment_version_workflow_id_workflow_id_fk", - "tableFrom": "workflow_deployment_version", - "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.workflow_edges": { - "name": "workflow_edges", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "workflow_id": { - "name": "workflow_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "source_block_id": { - "name": "source_block_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "target_block_id": { - "name": "target_block_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "source_handle": { - "name": "source_handle", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "target_handle": { - "name": "target_handle", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "workflow_edges_workflow_id_idx": { - "name": "workflow_edges_workflow_id_idx", - "columns": [ - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_edges_workflow_source_idx": { - "name": "workflow_edges_workflow_source_idx", - "columns": [ - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "source_block_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_edges_workflow_target_idx": { - "name": "workflow_edges_workflow_target_idx", - "columns": [ - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "target_block_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "workflow_edges_workflow_id_workflow_id_fk": { - "name": "workflow_edges_workflow_id_workflow_id_fk", - "tableFrom": "workflow_edges", - "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "workflow_edges_source_block_id_workflow_blocks_id_fk": { - "name": "workflow_edges_source_block_id_workflow_blocks_id_fk", - "tableFrom": "workflow_edges", - "tableTo": "workflow_blocks", - "columnsFrom": ["source_block_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "workflow_edges_target_block_id_workflow_blocks_id_fk": { - "name": "workflow_edges_target_block_id_workflow_blocks_id_fk", - "tableFrom": "workflow_edges", - "tableTo": "workflow_blocks", - "columnsFrom": ["target_block_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.workflow_execution_logs": { - "name": "workflow_execution_logs", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "workflow_id": { - "name": "workflow_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "execution_id": { - "name": "execution_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "state_snapshot_id": { - "name": "state_snapshot_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "deployment_version_id": { - "name": "deployment_version_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "level": { - "name": "level", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "trigger": { - "name": "trigger", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "started_at": { - "name": "started_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "ended_at": { - "name": "ended_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "total_duration_ms": { - "name": "total_duration_ms", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "execution_data": { - "name": "execution_data", - "type": "jsonb", - "primaryKey": false, - "notNull": true, - "default": "'{}'" - }, - "cost": { - "name": "cost", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "files": { - "name": "files", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "workflow_execution_logs_workflow_id_idx": { - "name": "workflow_execution_logs_workflow_id_idx", - "columns": [ - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_execution_logs_state_snapshot_id_idx": { - "name": "workflow_execution_logs_state_snapshot_id_idx", - "columns": [ - { - "expression": "state_snapshot_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_execution_logs_deployment_version_id_idx": { - "name": "workflow_execution_logs_deployment_version_id_idx", - "columns": [ - { - "expression": "deployment_version_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_execution_logs_trigger_idx": { - "name": "workflow_execution_logs_trigger_idx", - "columns": [ - { - "expression": "trigger", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_execution_logs_level_idx": { - "name": "workflow_execution_logs_level_idx", - "columns": [ - { - "expression": "level", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_execution_logs_started_at_idx": { - "name": "workflow_execution_logs_started_at_idx", - "columns": [ - { - "expression": "started_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_execution_logs_execution_id_unique": { - "name": "workflow_execution_logs_execution_id_unique", - "columns": [ - { - "expression": "execution_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_execution_logs_workflow_started_at_idx": { - "name": "workflow_execution_logs_workflow_started_at_idx", - "columns": [ - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "started_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "workflow_execution_logs_workflow_id_workflow_id_fk": { - "name": "workflow_execution_logs_workflow_id_workflow_id_fk", - "tableFrom": "workflow_execution_logs", - "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "workflow_execution_logs_state_snapshot_id_workflow_execution_snapshots_id_fk": { - "name": "workflow_execution_logs_state_snapshot_id_workflow_execution_snapshots_id_fk", - "tableFrom": "workflow_execution_logs", - "tableTo": "workflow_execution_snapshots", - "columnsFrom": ["state_snapshot_id"], - "columnsTo": ["id"], - "onDelete": "no action", - "onUpdate": "no action" - }, - "workflow_execution_logs_deployment_version_id_workflow_deployment_version_id_fk": { - "name": "workflow_execution_logs_deployment_version_id_workflow_deployment_version_id_fk", - "tableFrom": "workflow_execution_logs", - "tableTo": "workflow_deployment_version", - "columnsFrom": ["deployment_version_id"], - "columnsTo": ["id"], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.workflow_execution_snapshots": { - "name": "workflow_execution_snapshots", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "workflow_id": { - "name": "workflow_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "state_hash": { - "name": "state_hash", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "state_data": { - "name": "state_data", - "type": "jsonb", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "workflow_snapshots_workflow_id_idx": { - "name": "workflow_snapshots_workflow_id_idx", - "columns": [ - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_snapshots_hash_idx": { - "name": "workflow_snapshots_hash_idx", - "columns": [ - { - "expression": "state_hash", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_snapshots_workflow_hash_idx": { - "name": "workflow_snapshots_workflow_hash_idx", - "columns": [ - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "state_hash", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_snapshots_created_at_idx": { - "name": "workflow_snapshots_created_at_idx", - "columns": [ - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "workflow_execution_snapshots_workflow_id_workflow_id_fk": { - "name": "workflow_execution_snapshots_workflow_id_workflow_id_fk", - "tableFrom": "workflow_execution_snapshots", - "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.workflow_folder": { - "name": "workflow_folder", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "workspace_id": { - "name": "workspace_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "parent_id": { - "name": "parent_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "color": { - "name": "color", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'#6B7280'" - }, - "is_expanded": { - "name": "is_expanded", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "sort_order": { - "name": "sort_order", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "workflow_folder_user_idx": { - "name": "workflow_folder_user_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_folder_workspace_parent_idx": { - "name": "workflow_folder_workspace_parent_idx", - "columns": [ - { - "expression": "workspace_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "parent_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_folder_parent_sort_idx": { - "name": "workflow_folder_parent_sort_idx", - "columns": [ - { - "expression": "parent_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "sort_order", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "workflow_folder_user_id_user_id_fk": { - "name": "workflow_folder_user_id_user_id_fk", - "tableFrom": "workflow_folder", - "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "workflow_folder_workspace_id_workspace_id_fk": { - "name": "workflow_folder_workspace_id_workspace_id_fk", - "tableFrom": "workflow_folder", - "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.workflow_mcp_server": { - "name": "workflow_mcp_server", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "workspace_id": { - "name": "workspace_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_by": { - "name": "created_by", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "is_published": { - "name": "is_published", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "published_at": { - "name": "published_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "workflow_mcp_server_workspace_id_idx": { - "name": "workflow_mcp_server_workspace_id_idx", - "columns": [ - { - "expression": "workspace_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_mcp_server_created_by_idx": { - "name": "workflow_mcp_server_created_by_idx", - "columns": [ - { - "expression": "created_by", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_mcp_server_is_published_idx": { - "name": "workflow_mcp_server_is_published_idx", - "columns": [ - { - "expression": "is_published", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "workflow_mcp_server_workspace_id_workspace_id_fk": { - "name": "workflow_mcp_server_workspace_id_workspace_id_fk", - "tableFrom": "workflow_mcp_server", - "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "workflow_mcp_server_created_by_user_id_fk": { - "name": "workflow_mcp_server_created_by_user_id_fk", - "tableFrom": "workflow_mcp_server", - "tableTo": "user", - "columnsFrom": ["created_by"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.workflow_mcp_tool": { - "name": "workflow_mcp_tool", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "server_id": { - "name": "server_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "workflow_id": { - "name": "workflow_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "tool_name": { - "name": "tool_name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "tool_description": { - "name": "tool_description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "parameter_schema": { - "name": "parameter_schema", - "type": "json", - "primaryKey": false, - "notNull": true, - "default": "'{}'" - }, - "is_enabled": { - "name": "is_enabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "workflow_mcp_tool_server_id_idx": { - "name": "workflow_mcp_tool_server_id_idx", - "columns": [ - { - "expression": "server_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_mcp_tool_workflow_id_idx": { - "name": "workflow_mcp_tool_workflow_id_idx", - "columns": [ - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_mcp_tool_server_workflow_unique": { - "name": "workflow_mcp_tool_server_workflow_unique", - "columns": [ - { - "expression": "server_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "workflow_mcp_tool_server_id_workflow_mcp_server_id_fk": { - "name": "workflow_mcp_tool_server_id_workflow_mcp_server_id_fk", - "tableFrom": "workflow_mcp_tool", - "tableTo": "workflow_mcp_server", - "columnsFrom": ["server_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "workflow_mcp_tool_workflow_id_workflow_id_fk": { - "name": "workflow_mcp_tool_workflow_id_workflow_id_fk", - "tableFrom": "workflow_mcp_tool", - "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.workflow_schedule": { - "name": "workflow_schedule", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "workflow_id": { - "name": "workflow_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "block_id": { - "name": "block_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "cron_expression": { - "name": "cron_expression", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "next_run_at": { - "name": "next_run_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "last_ran_at": { - "name": "last_ran_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "last_queued_at": { - "name": "last_queued_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "trigger_type": { - "name": "trigger_type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "timezone": { - "name": "timezone", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'UTC'" - }, - "failed_count": { - "name": "failed_count", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'active'" - }, - "last_failed_at": { - "name": "last_failed_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "workflow_schedule_workflow_block_unique": { - "name": "workflow_schedule_workflow_block_unique", - "columns": [ - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "block_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "workflow_schedule_workflow_id_workflow_id_fk": { - "name": "workflow_schedule_workflow_id_workflow_id_fk", - "tableFrom": "workflow_schedule", - "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "workflow_schedule_block_id_workflow_blocks_id_fk": { - "name": "workflow_schedule_block_id_workflow_blocks_id_fk", - "tableFrom": "workflow_schedule", - "tableTo": "workflow_blocks", - "columnsFrom": ["block_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.workflow_subflows": { - "name": "workflow_subflows", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "workflow_id": { - "name": "workflow_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "config": { - "name": "config", - "type": "jsonb", - "primaryKey": false, - "notNull": true, - "default": "'{}'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "workflow_subflows_workflow_id_idx": { - "name": "workflow_subflows_workflow_id_idx", - "columns": [ - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workflow_subflows_workflow_type_idx": { - "name": "workflow_subflows_workflow_type_idx", - "columns": [ - { - "expression": "workflow_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "type", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "workflow_subflows_workflow_id_workflow_id_fk": { - "name": "workflow_subflows_workflow_id_workflow_id_fk", - "tableFrom": "workflow_subflows", - "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.workspace": { - "name": "workspace", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "owner_id": { - "name": "owner_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "billed_account_user_id": { - "name": "billed_account_user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "allow_personal_api_keys": { - "name": "allow_personal_api_keys", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "workspace_owner_id_user_id_fk": { - "name": "workspace_owner_id_user_id_fk", - "tableFrom": "workspace", - "tableTo": "user", - "columnsFrom": ["owner_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "workspace_billed_account_user_id_user_id_fk": { - "name": "workspace_billed_account_user_id_user_id_fk", - "tableFrom": "workspace", - "tableTo": "user", - "columnsFrom": ["billed_account_user_id"], - "columnsTo": ["id"], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.workspace_environment": { - "name": "workspace_environment", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "workspace_id": { - "name": "workspace_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "variables": { - "name": "variables", - "type": "json", - "primaryKey": false, - "notNull": true, - "default": "'{}'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "workspace_environment_workspace_unique": { - "name": "workspace_environment_workspace_unique", - "columns": [ - { - "expression": "workspace_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "workspace_environment_workspace_id_workspace_id_fk": { - "name": "workspace_environment_workspace_id_workspace_id_fk", - "tableFrom": "workspace_environment", - "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.workspace_file": { - "name": "workspace_file", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "workspace_id": { - "name": "workspace_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "key": { - "name": "key", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "size": { - "name": "size", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "uploaded_by": { - "name": "uploaded_by", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "uploaded_at": { - "name": "uploaded_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "workspace_file_workspace_id_idx": { - "name": "workspace_file_workspace_id_idx", - "columns": [ - { - "expression": "workspace_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workspace_file_key_idx": { - "name": "workspace_file_key_idx", - "columns": [ - { - "expression": "key", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "workspace_file_workspace_id_workspace_id_fk": { - "name": "workspace_file_workspace_id_workspace_id_fk", - "tableFrom": "workspace_file", - "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "workspace_file_uploaded_by_user_id_fk": { - "name": "workspace_file_uploaded_by_user_id_fk", - "tableFrom": "workspace_file", - "tableTo": "user", - "columnsFrom": ["uploaded_by"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "workspace_file_key_unique": { - "name": "workspace_file_key_unique", - "nullsNotDistinct": false, - "columns": ["key"] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.workspace_files": { - "name": "workspace_files", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "key": { - "name": "key", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "workspace_id": { - "name": "workspace_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "context": { - "name": "context", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "original_name": { - "name": "original_name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "content_type": { - "name": "content_type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "size": { - "name": "size", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "uploaded_at": { - "name": "uploaded_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "workspace_files_key_idx": { - "name": "workspace_files_key_idx", - "columns": [ - { - "expression": "key", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workspace_files_user_id_idx": { - "name": "workspace_files_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workspace_files_workspace_id_idx": { - "name": "workspace_files_workspace_id_idx", - "columns": [ - { - "expression": "workspace_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workspace_files_context_idx": { - "name": "workspace_files_context_idx", - "columns": [ - { - "expression": "context", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "workspace_files_user_id_user_id_fk": { - "name": "workspace_files_user_id_user_id_fk", - "tableFrom": "workspace_files", - "tableTo": "user", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "workspace_files_workspace_id_workspace_id_fk": { - "name": "workspace_files_workspace_id_workspace_id_fk", - "tableFrom": "workspace_files", - "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "workspace_files_key_unique": { - "name": "workspace_files_key_unique", - "nullsNotDistinct": false, - "columns": ["key"] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.workspace_invitation": { - "name": "workspace_invitation", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "workspace_id": { - "name": "workspace_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "email": { - "name": "email", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "inviter_id": { - "name": "inviter_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "role": { - "name": "role", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'member'" - }, - "status": { - "name": "status", - "type": "workspace_invitation_status", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'pending'" - }, - "token": { - "name": "token", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "permissions": { - "name": "permissions", - "type": "permission_type", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'admin'" - }, - "org_invitation_id": { - "name": "org_invitation_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "workspace_invitation_workspace_id_workspace_id_fk": { - "name": "workspace_invitation_workspace_id_workspace_id_fk", - "tableFrom": "workspace_invitation", - "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "workspace_invitation_inviter_id_user_id_fk": { - "name": "workspace_invitation_inviter_id_user_id_fk", - "tableFrom": "workspace_invitation", - "tableTo": "user", - "columnsFrom": ["inviter_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "workspace_invitation_token_unique": { - "name": "workspace_invitation_token_unique", - "nullsNotDistinct": false, - "columns": ["token"] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.workspace_notification_delivery": { - "name": "workspace_notification_delivery", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "subscription_id": { - "name": "subscription_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "workflow_id": { - "name": "workflow_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "execution_id": { - "name": "execution_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "status": { - "name": "status", - "type": "notification_delivery_status", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'pending'" - }, - "attempts": { - "name": "attempts", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "last_attempt_at": { - "name": "last_attempt_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "next_attempt_at": { - "name": "next_attempt_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "response_status": { - "name": "response_status", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "response_body": { - "name": "response_body", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "error_message": { - "name": "error_message", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "workspace_notification_delivery_subscription_id_idx": { - "name": "workspace_notification_delivery_subscription_id_idx", - "columns": [ - { - "expression": "subscription_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workspace_notification_delivery_execution_id_idx": { - "name": "workspace_notification_delivery_execution_id_idx", - "columns": [ - { - "expression": "execution_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workspace_notification_delivery_status_idx": { - "name": "workspace_notification_delivery_status_idx", - "columns": [ - { - "expression": "status", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workspace_notification_delivery_next_attempt_idx": { - "name": "workspace_notification_delivery_next_attempt_idx", - "columns": [ - { - "expression": "next_attempt_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "workspace_notification_delivery_subscription_id_workspace_notification_subscription_id_fk": { - "name": "workspace_notification_delivery_subscription_id_workspace_notification_subscription_id_fk", - "tableFrom": "workspace_notification_delivery", - "tableTo": "workspace_notification_subscription", - "columnsFrom": ["subscription_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "workspace_notification_delivery_workflow_id_workflow_id_fk": { - "name": "workspace_notification_delivery_workflow_id_workflow_id_fk", - "tableFrom": "workspace_notification_delivery", - "tableTo": "workflow", - "columnsFrom": ["workflow_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.workspace_notification_subscription": { - "name": "workspace_notification_subscription", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "workspace_id": { - "name": "workspace_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "notification_type": { - "name": "notification_type", - "type": "notification_type", - "typeSchema": "public", - "primaryKey": false, - "notNull": true - }, - "workflow_ids": { - "name": "workflow_ids", - "type": "text[]", - "primaryKey": false, - "notNull": true, - "default": "'{}'::text[]" - }, - "all_workflows": { - "name": "all_workflows", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "level_filter": { - "name": "level_filter", - "type": "text[]", - "primaryKey": false, - "notNull": true, - "default": "ARRAY['info', 'error']::text[]" - }, - "trigger_filter": { - "name": "trigger_filter", - "type": "text[]", - "primaryKey": false, - "notNull": true, - "default": "ARRAY['api', 'webhook', 'schedule', 'manual', 'chat']::text[]" - }, - "include_final_output": { - "name": "include_final_output", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "include_trace_spans": { - "name": "include_trace_spans", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "include_rate_limits": { - "name": "include_rate_limits", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "include_usage_data": { - "name": "include_usage_data", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "webhook_config": { - "name": "webhook_config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "email_recipients": { - "name": "email_recipients", - "type": "text[]", - "primaryKey": false, - "notNull": false - }, - "slack_config": { - "name": "slack_config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "alert_config": { - "name": "alert_config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "last_alert_at": { - "name": "last_alert_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "active": { - "name": "active", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "created_by": { - "name": "created_by", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "workspace_notification_workspace_id_idx": { - "name": "workspace_notification_workspace_id_idx", - "columns": [ - { - "expression": "workspace_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workspace_notification_active_idx": { - "name": "workspace_notification_active_idx", - "columns": [ - { - "expression": "active", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "workspace_notification_type_idx": { - "name": "workspace_notification_type_idx", - "columns": [ - { - "expression": "notification_type", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "workspace_notification_subscription_workspace_id_workspace_id_fk": { - "name": "workspace_notification_subscription_workspace_id_workspace_id_fk", - "tableFrom": "workspace_notification_subscription", - "tableTo": "workspace", - "columnsFrom": ["workspace_id"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "workspace_notification_subscription_created_by_user_id_fk": { - "name": "workspace_notification_subscription_created_by_user_id_fk", - "tableFrom": "workspace_notification_subscription", - "tableTo": "user", - "columnsFrom": ["created_by"], - "columnsTo": ["id"], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - } - }, - "enums": { - "public.billing_blocked_reason": { - "name": "billing_blocked_reason", - "schema": "public", - "values": ["payment_failed", "dispute"] - }, - "public.notification_delivery_status": { - "name": "notification_delivery_status", - "schema": "public", - "values": ["pending", "in_progress", "success", "failed"] - }, - "public.notification_type": { - "name": "notification_type", - "schema": "public", - "values": ["webhook", "email", "slack"] - }, - "public.permission_type": { - "name": "permission_type", - "schema": "public", - "values": ["admin", "write", "read"] - }, - "public.template_creator_type": { - "name": "template_creator_type", - "schema": "public", - "values": ["user", "organization"] - }, - "public.template_status": { - "name": "template_status", - "schema": "public", - "values": ["pending", "approved", "rejected"] - }, - "public.workspace_invitation_status": { - "name": "workspace_invitation_status", - "schema": "public", - "values": ["pending", "accepted", "rejected", "cancelled"] - } - }, - "schemas": {}, - "sequences": {}, - "roles": {}, - "policies": {}, - "views": {}, - "_meta": { - "columns": {}, - "schemas": {}, - "tables": {} - } -} diff --git a/packages/db/migrations/meta/_journal.json b/packages/db/migrations/meta/_journal.json index 4b22dd9e02..f793d74bf8 100644 --- a/packages/db/migrations/meta/_journal.json +++ b/packages/db/migrations/meta/_journal.json @@ -855,13 +855,6 @@ "when": 1765587157593, "tag": "0122_pale_absorbing_man", "breakpoints": true - }, - { - "idx": 123, - "version": "7", - "when": 1765929938586, - "tag": "0123_acoustic_hellcat", - "breakpoints": true } ] } From 1f22d7a9eca60ae813521d554942386d68a504de Mon Sep 17 00:00:00 2001 From: "priyanshu.solanki" Date: Wed, 17 Dec 2025 17:37:31 -0700 Subject: [PATCH 06/27] fix --- ...ustic_hellcat.sql => 0124_amused_lyja.sql} | 0 .../db/migrations/meta/0123_snapshot.json | 7722 +++++++++++++++ .../db/migrations/meta/0124_snapshot.json | 8363 +++++++++++++++++ packages/db/migrations/meta/_journal.json | 16 +- 4 files changed, 16100 insertions(+), 1 deletion(-) rename packages/db/migrations/{0123_acoustic_hellcat.sql => 0124_amused_lyja.sql} (100%) create mode 100644 packages/db/migrations/meta/0123_snapshot.json create mode 100644 packages/db/migrations/meta/0124_snapshot.json diff --git a/packages/db/migrations/0123_acoustic_hellcat.sql b/packages/db/migrations/0124_amused_lyja.sql similarity index 100% rename from packages/db/migrations/0123_acoustic_hellcat.sql rename to packages/db/migrations/0124_amused_lyja.sql diff --git a/packages/db/migrations/meta/0123_snapshot.json b/packages/db/migrations/meta/0123_snapshot.json new file mode 100644 index 0000000000..419a02d6f5 --- /dev/null +++ b/packages/db/migrations/meta/0123_snapshot.json @@ -0,0 +1,7722 @@ +{ + "id": "1be6ebb3-fe8a-4abd-9f4d-cfb8341f5319", + "prevId": "ec1ad797-549e-4e4e-a40b-f2a865ae4c4c", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "account_user_id_idx": { + "name": "account_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_account_on_account_id_provider_id": { + "name": "idx_account_on_account_id_provider_id", + "columns": [ + { + "expression": "account_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "account_user_provider_account_unique": { + "name": "account_user_provider_account_unique", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "account_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.api_key": { + "name": "api_key", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'personal'" + }, + "last_used": { + "name": "last_used", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "api_key_user_id_user_id_fk": { + "name": "api_key_user_id_user_id_fk", + "tableFrom": "api_key", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "api_key_workspace_id_workspace_id_fk": { + "name": "api_key_workspace_id_workspace_id_fk", + "tableFrom": "api_key", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "api_key_created_by_user_id_fk": { + "name": "api_key_created_by_user_id_fk", + "tableFrom": "api_key", + "tableTo": "user", + "columnsFrom": ["created_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "api_key_key_unique": { + "name": "api_key_key_unique", + "nullsNotDistinct": false, + "columns": ["key"] + } + }, + "policies": {}, + "checkConstraints": { + "workspace_type_check": { + "name": "workspace_type_check", + "value": "(type = 'workspace' AND workspace_id IS NOT NULL) OR (type = 'personal' AND workspace_id IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.chat": { + "name": "chat", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "customizations": { + "name": "customizations", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "auth_type": { + "name": "auth_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'public'" + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "allowed_emails": { + "name": "allowed_emails", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'[]'" + }, + "output_configs": { + "name": "output_configs", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'[]'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "identifier_idx": { + "name": "identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "chat_workflow_id_workflow_id_fk": { + "name": "chat_workflow_id_workflow_id_fk", + "tableFrom": "chat", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "chat_user_id_user_id_fk": { + "name": "chat_user_id_user_id_fk", + "tableFrom": "chat", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.copilot_chats": { + "name": "copilot_chats", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "messages": { + "name": "messages", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'claude-3-7-sonnet-latest'" + }, + "conversation_id": { + "name": "conversation_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "preview_yaml": { + "name": "preview_yaml", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "plan_artifact": { + "name": "plan_artifact", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "copilot_chats_user_id_idx": { + "name": "copilot_chats_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_workflow_id_idx": { + "name": "copilot_chats_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_user_workflow_idx": { + "name": "copilot_chats_user_workflow_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_created_at_idx": { + "name": "copilot_chats_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_updated_at_idx": { + "name": "copilot_chats_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "copilot_chats_user_id_user_id_fk": { + "name": "copilot_chats_user_id_user_id_fk", + "tableFrom": "copilot_chats", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "copilot_chats_workflow_id_workflow_id_fk": { + "name": "copilot_chats_workflow_id_workflow_id_fk", + "tableFrom": "copilot_chats", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.copilot_feedback": { + "name": "copilot_feedback", + "schema": "", + "columns": { + "feedback_id": { + "name": "feedback_id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chat_id": { + "name": "chat_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_query": { + "name": "user_query", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "agent_response": { + "name": "agent_response", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "is_positive": { + "name": "is_positive", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "feedback": { + "name": "feedback", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workflow_yaml": { + "name": "workflow_yaml", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "copilot_feedback_user_id_idx": { + "name": "copilot_feedback_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_feedback_chat_id_idx": { + "name": "copilot_feedback_chat_id_idx", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_feedback_user_chat_idx": { + "name": "copilot_feedback_user_chat_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_feedback_is_positive_idx": { + "name": "copilot_feedback_is_positive_idx", + "columns": [ + { + "expression": "is_positive", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_feedback_created_at_idx": { + "name": "copilot_feedback_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "copilot_feedback_user_id_user_id_fk": { + "name": "copilot_feedback_user_id_user_id_fk", + "tableFrom": "copilot_feedback", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "copilot_feedback_chat_id_copilot_chats_id_fk": { + "name": "copilot_feedback_chat_id_copilot_chats_id_fk", + "tableFrom": "copilot_feedback", + "tableTo": "copilot_chats", + "columnsFrom": ["chat_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.custom_tools": { + "name": "custom_tools", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "schema": { + "name": "schema", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "code": { + "name": "code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "custom_tools_workspace_id_idx": { + "name": "custom_tools_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "custom_tools_workspace_title_unique": { + "name": "custom_tools_workspace_title_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "title", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "custom_tools_workspace_id_workspace_id_fk": { + "name": "custom_tools_workspace_id_workspace_id_fk", + "tableFrom": "custom_tools", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "custom_tools_user_id_user_id_fk": { + "name": "custom_tools_user_id_user_id_fk", + "tableFrom": "custom_tools", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.docs_embeddings": { + "name": "docs_embeddings", + "schema": "", + "columns": { + "chunk_id": { + "name": "chunk_id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "chunk_text": { + "name": "chunk_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_document": { + "name": "source_document", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_link": { + "name": "source_link", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "header_text": { + "name": "header_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "header_level": { + "name": "header_level", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "token_count": { + "name": "token_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "embedding": { + "name": "embedding", + "type": "vector(1536)", + "primaryKey": false, + "notNull": true + }, + "embedding_model": { + "name": "embedding_model", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text-embedding-3-small'" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "chunk_text_tsv": { + "name": "chunk_text_tsv", + "type": "tsvector", + "primaryKey": false, + "notNull": false, + "generated": { + "as": "to_tsvector('english', \"docs_embeddings\".\"chunk_text\")", + "type": "stored" + } + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "docs_emb_source_document_idx": { + "name": "docs_emb_source_document_idx", + "columns": [ + { + "expression": "source_document", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_emb_header_level_idx": { + "name": "docs_emb_header_level_idx", + "columns": [ + { + "expression": "header_level", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_emb_source_header_idx": { + "name": "docs_emb_source_header_idx", + "columns": [ + { + "expression": "source_document", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "header_level", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_emb_model_idx": { + "name": "docs_emb_model_idx", + "columns": [ + { + "expression": "embedding_model", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_emb_created_at_idx": { + "name": "docs_emb_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_embedding_vector_hnsw_idx": { + "name": "docs_embedding_vector_hnsw_idx", + "columns": [ + { + "expression": "embedding", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "vector_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": { + "m": 16, + "ef_construction": 64 + } + }, + "docs_emb_metadata_gin_idx": { + "name": "docs_emb_metadata_gin_idx", + "columns": [ + { + "expression": "metadata", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + }, + "docs_emb_chunk_text_fts_idx": { + "name": "docs_emb_chunk_text_fts_idx", + "columns": [ + { + "expression": "chunk_text_tsv", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "docs_embedding_not_null_check": { + "name": "docs_embedding_not_null_check", + "value": "\"embedding\" IS NOT NULL" + }, + "docs_header_level_check": { + "name": "docs_header_level_check", + "value": "\"header_level\" >= 1 AND \"header_level\" <= 6" + } + }, + "isRLSEnabled": false + }, + "public.document": { + "name": "document", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "filename": { + "name": "filename", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "file_url": { + "name": "file_url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "file_size": { + "name": "file_size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "mime_type": { + "name": "mime_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chunk_count": { + "name": "chunk_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "token_count": { + "name": "token_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "character_count": { + "name": "character_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "processing_status": { + "name": "processing_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "processing_started_at": { + "name": "processing_started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "processing_completed_at": { + "name": "processing_completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "processing_error": { + "name": "processing_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "tag1": { + "name": "tag1", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag2": { + "name": "tag2", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag3": { + "name": "tag3", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag4": { + "name": "tag4", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag5": { + "name": "tag5", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag6": { + "name": "tag6", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag7": { + "name": "tag7", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "uploaded_at": { + "name": "uploaded_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "doc_kb_id_idx": { + "name": "doc_kb_id_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_filename_idx": { + "name": "doc_filename_idx", + "columns": [ + { + "expression": "filename", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_processing_status_idx": { + "name": "doc_processing_status_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "processing_status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag1_idx": { + "name": "doc_tag1_idx", + "columns": [ + { + "expression": "tag1", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag2_idx": { + "name": "doc_tag2_idx", + "columns": [ + { + "expression": "tag2", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag3_idx": { + "name": "doc_tag3_idx", + "columns": [ + { + "expression": "tag3", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag4_idx": { + "name": "doc_tag4_idx", + "columns": [ + { + "expression": "tag4", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag5_idx": { + "name": "doc_tag5_idx", + "columns": [ + { + "expression": "tag5", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag6_idx": { + "name": "doc_tag6_idx", + "columns": [ + { + "expression": "tag6", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag7_idx": { + "name": "doc_tag7_idx", + "columns": [ + { + "expression": "tag7", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "document_knowledge_base_id_knowledge_base_id_fk": { + "name": "document_knowledge_base_id_knowledge_base_id_fk", + "tableFrom": "document", + "tableTo": "knowledge_base", + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.embedding": { + "name": "embedding", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "document_id": { + "name": "document_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chunk_index": { + "name": "chunk_index", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "chunk_hash": { + "name": "chunk_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content_length": { + "name": "content_length", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "token_count": { + "name": "token_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "embedding": { + "name": "embedding", + "type": "vector(1536)", + "primaryKey": false, + "notNull": false + }, + "embedding_model": { + "name": "embedding_model", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text-embedding-3-small'" + }, + "start_offset": { + "name": "start_offset", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "end_offset": { + "name": "end_offset", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "tag1": { + "name": "tag1", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag2": { + "name": "tag2", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag3": { + "name": "tag3", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag4": { + "name": "tag4", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag5": { + "name": "tag5", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag6": { + "name": "tag6", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag7": { + "name": "tag7", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "content_tsv": { + "name": "content_tsv", + "type": "tsvector", + "primaryKey": false, + "notNull": false, + "generated": { + "as": "to_tsvector('english', \"embedding\".\"content\")", + "type": "stored" + } + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "emb_kb_id_idx": { + "name": "emb_kb_id_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_doc_id_idx": { + "name": "emb_doc_id_idx", + "columns": [ + { + "expression": "document_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_doc_chunk_idx": { + "name": "emb_doc_chunk_idx", + "columns": [ + { + "expression": "document_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "chunk_index", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_kb_model_idx": { + "name": "emb_kb_model_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "embedding_model", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_kb_enabled_idx": { + "name": "emb_kb_enabled_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_doc_enabled_idx": { + "name": "emb_doc_enabled_idx", + "columns": [ + { + "expression": "document_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "embedding_vector_hnsw_idx": { + "name": "embedding_vector_hnsw_idx", + "columns": [ + { + "expression": "embedding", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "vector_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": { + "m": 16, + "ef_construction": 64 + } + }, + "emb_tag1_idx": { + "name": "emb_tag1_idx", + "columns": [ + { + "expression": "tag1", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag2_idx": { + "name": "emb_tag2_idx", + "columns": [ + { + "expression": "tag2", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag3_idx": { + "name": "emb_tag3_idx", + "columns": [ + { + "expression": "tag3", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag4_idx": { + "name": "emb_tag4_idx", + "columns": [ + { + "expression": "tag4", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag5_idx": { + "name": "emb_tag5_idx", + "columns": [ + { + "expression": "tag5", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag6_idx": { + "name": "emb_tag6_idx", + "columns": [ + { + "expression": "tag6", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag7_idx": { + "name": "emb_tag7_idx", + "columns": [ + { + "expression": "tag7", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_content_fts_idx": { + "name": "emb_content_fts_idx", + "columns": [ + { + "expression": "content_tsv", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + } + }, + "foreignKeys": { + "embedding_knowledge_base_id_knowledge_base_id_fk": { + "name": "embedding_knowledge_base_id_knowledge_base_id_fk", + "tableFrom": "embedding", + "tableTo": "knowledge_base", + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "embedding_document_id_document_id_fk": { + "name": "embedding_document_id_document_id_fk", + "tableFrom": "embedding", + "tableTo": "document", + "columnsFrom": ["document_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "embedding_not_null_check": { + "name": "embedding_not_null_check", + "value": "\"embedding\" IS NOT NULL" + } + }, + "isRLSEnabled": false + }, + "public.environment": { + "name": "environment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "variables": { + "name": "variables", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "environment_user_id_user_id_fk": { + "name": "environment_user_id_user_id_fk", + "tableFrom": "environment", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "environment_user_id_unique": { + "name": "environment_user_id_unique", + "nullsNotDistinct": false, + "columns": ["user_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.idempotency_key": { + "name": "idempotency_key", + "schema": "", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "namespace": { + "name": "namespace", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'default'" + }, + "result": { + "name": "result", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "idempotency_key_namespace_unique": { + "name": "idempotency_key_namespace_unique", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "namespace", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idempotency_key_created_at_idx": { + "name": "idempotency_key_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idempotency_key_namespace_idx": { + "name": "idempotency_key_namespace_idx", + "columns": [ + { + "expression": "namespace", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.invitation": { + "name": "invitation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "invitation_email_idx": { + "name": "invitation_email_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "invitation_organization_id_idx": { + "name": "invitation_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "invitation_inviter_id_user_id_fk": { + "name": "invitation_inviter_id_user_id_fk", + "tableFrom": "invitation", + "tableTo": "user", + "columnsFrom": ["inviter_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "invitation_organization_id_organization_id_fk": { + "name": "invitation_organization_id_organization_id_fk", + "tableFrom": "invitation", + "tableTo": "organization", + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knowledge_base": { + "name": "knowledge_base", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "token_count": { + "name": "token_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "embedding_model": { + "name": "embedding_model", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text-embedding-3-small'" + }, + "embedding_dimension": { + "name": "embedding_dimension", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1536 + }, + "chunking_config": { + "name": "chunking_config", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{\"maxSize\": 1024, \"minSize\": 1, \"overlap\": 200}'" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "kb_user_id_idx": { + "name": "kb_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_workspace_id_idx": { + "name": "kb_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_user_workspace_idx": { + "name": "kb_user_workspace_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_deleted_at_idx": { + "name": "kb_deleted_at_idx", + "columns": [ + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knowledge_base_user_id_user_id_fk": { + "name": "knowledge_base_user_id_user_id_fk", + "tableFrom": "knowledge_base", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knowledge_base_workspace_id_workspace_id_fk": { + "name": "knowledge_base_workspace_id_workspace_id_fk", + "tableFrom": "knowledge_base", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knowledge_base_tag_definitions": { + "name": "knowledge_base_tag_definitions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tag_slot": { + "name": "tag_slot", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "field_type": { + "name": "field_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "kb_tag_definitions_kb_slot_idx": { + "name": "kb_tag_definitions_kb_slot_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tag_slot", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_tag_definitions_kb_display_name_idx": { + "name": "kb_tag_definitions_kb_display_name_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "display_name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_tag_definitions_kb_id_idx": { + "name": "kb_tag_definitions_kb_id_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knowledge_base_tag_definitions_knowledge_base_id_knowledge_base_id_fk": { + "name": "knowledge_base_tag_definitions_knowledge_base_id_knowledge_base_id_fk", + "tableFrom": "knowledge_base_tag_definitions", + "tableTo": "knowledge_base", + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.mcp_servers": { + "name": "mcp_servers", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "transport": { + "name": "transport", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "headers": { + "name": "headers", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "timeout": { + "name": "timeout", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 30000 + }, + "retries": { + "name": "retries", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 3 + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "last_connected": { + "name": "last_connected", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "connection_status": { + "name": "connection_status", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'disconnected'" + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status_config": { + "name": "status_config", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "tool_count": { + "name": "tool_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "last_tools_refresh": { + "name": "last_tools_refresh", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "total_requests": { + "name": "total_requests", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "last_used": { + "name": "last_used", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "mcp_servers_workspace_enabled_idx": { + "name": "mcp_servers_workspace_enabled_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "mcp_servers_workspace_deleted_idx": { + "name": "mcp_servers_workspace_deleted_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "mcp_servers_workspace_id_workspace_id_fk": { + "name": "mcp_servers_workspace_id_workspace_id_fk", + "tableFrom": "mcp_servers", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mcp_servers_created_by_user_id_fk": { + "name": "mcp_servers_created_by_user_id_fk", + "tableFrom": "mcp_servers", + "tableTo": "user", + "columnsFrom": ["created_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.member": { + "name": "member", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "member_user_id_idx": { + "name": "member_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "member_organization_id_idx": { + "name": "member_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "member_user_id_user_id_fk": { + "name": "member_user_id_user_id_fk", + "tableFrom": "member", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "member_organization_id_organization_id_fk": { + "name": "member_organization_id_organization_id_fk", + "tableFrom": "member", + "tableTo": "organization", + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.memory": { + "name": "memory", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "memory_key_idx": { + "name": "memory_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "memory_workflow_idx": { + "name": "memory_workflow_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "memory_workflow_key_idx": { + "name": "memory_workflow_key_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "memory_workflow_id_workflow_id_fk": { + "name": "memory_workflow_id_workflow_id_fk", + "tableFrom": "memory", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organization": { + "name": "organization", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "logo": { + "name": "logo", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "org_usage_limit": { + "name": "org_usage_limit", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "storage_used_bytes": { + "name": "storage_used_bytes", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "departed_member_usage": { + "name": "departed_member_usage", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "credit_balance": { + "name": "credit_balance", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.paused_executions": { + "name": "paused_executions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_id": { + "name": "execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_snapshot": { + "name": "execution_snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "pause_points": { + "name": "pause_points", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "total_pause_count": { + "name": "total_pause_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "resumed_count": { + "name": "resumed_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'paused'" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "paused_at": { + "name": "paused_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "paused_executions_workflow_id_idx": { + "name": "paused_executions_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "paused_executions_status_idx": { + "name": "paused_executions_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "paused_executions_execution_id_unique": { + "name": "paused_executions_execution_id_unique", + "columns": [ + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "paused_executions_workflow_id_workflow_id_fk": { + "name": "paused_executions_workflow_id_workflow_id_fk", + "tableFrom": "paused_executions", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.permissions": { + "name": "permissions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "permission_type": { + "name": "permission_type", + "type": "permission_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "permissions_user_id_idx": { + "name": "permissions_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_entity_idx": { + "name": "permissions_entity_idx", + "columns": [ + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_user_entity_type_idx": { + "name": "permissions_user_entity_type_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_user_entity_permission_idx": { + "name": "permissions_user_entity_permission_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "permission_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_user_entity_idx": { + "name": "permissions_user_entity_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_unique_constraint": { + "name": "permissions_unique_constraint", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "permissions_user_id_user_id_fk": { + "name": "permissions_user_id_user_id_fk", + "tableFrom": "permissions", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.rate_limit_bucket": { + "name": "rate_limit_bucket", + "schema": "", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tokens": { + "name": "tokens", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "last_refill_at": { + "name": "last_refill_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.resume_queue": { + "name": "resume_queue", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "paused_execution_id": { + "name": "paused_execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parent_execution_id": { + "name": "parent_execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "new_execution_id": { + "name": "new_execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "context_id": { + "name": "context_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resume_input": { + "name": "resume_input", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "queued_at": { + "name": "queued_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "claimed_at": { + "name": "claimed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "failure_reason": { + "name": "failure_reason", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "resume_queue_parent_status_idx": { + "name": "resume_queue_parent_status_idx", + "columns": [ + { + "expression": "parent_execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "queued_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "resume_queue_new_execution_idx": { + "name": "resume_queue_new_execution_idx", + "columns": [ + { + "expression": "new_execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resume_queue_paused_execution_id_paused_executions_id_fk": { + "name": "resume_queue_paused_execution_id_paused_executions_id_fk", + "tableFrom": "resume_queue", + "tableTo": "paused_executions", + "columnsFrom": ["paused_execution_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "active_organization_id": { + "name": "active_organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "session_user_id_idx": { + "name": "session_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "session_token_idx": { + "name": "session_token_idx", + "columns": [ + { + "expression": "token", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "session_active_organization_id_organization_id_fk": { + "name": "session_active_organization_id_organization_id_fk", + "tableFrom": "session", + "tableTo": "organization", + "columnsFrom": ["active_organization_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": ["token"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.settings": { + "name": "settings", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "theme": { + "name": "theme", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'system'" + }, + "auto_connect": { + "name": "auto_connect", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "telemetry_enabled": { + "name": "telemetry_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "email_preferences": { + "name": "email_preferences", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "billing_usage_notifications_enabled": { + "name": "billing_usage_notifications_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "show_training_controls": { + "name": "show_training_controls", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "super_user_mode_enabled": { + "name": "super_user_mode_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "error_notifications_enabled": { + "name": "error_notifications_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "copilot_enabled_models": { + "name": "copilot_enabled_models", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "copilot_auto_allowed_tools": { + "name": "copilot_auto_allowed_tools", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "settings_user_id_user_id_fk": { + "name": "settings_user_id_user_id_fk", + "tableFrom": "settings", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "settings_user_id_unique": { + "name": "settings_user_id_unique", + "nullsNotDistinct": false, + "columns": ["user_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sso_provider": { + "name": "sso_provider", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "issuer": { + "name": "issuer", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "domain": { + "name": "domain", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "oidc_config": { + "name": "oidc_config", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "saml_config": { + "name": "saml_config", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "sso_provider_provider_id_idx": { + "name": "sso_provider_provider_id_idx", + "columns": [ + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sso_provider_domain_idx": { + "name": "sso_provider_domain_idx", + "columns": [ + { + "expression": "domain", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sso_provider_user_id_idx": { + "name": "sso_provider_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sso_provider_organization_id_idx": { + "name": "sso_provider_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "sso_provider_user_id_user_id_fk": { + "name": "sso_provider_user_id_user_id_fk", + "tableFrom": "sso_provider", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "sso_provider_organization_id_organization_id_fk": { + "name": "sso_provider_organization_id_organization_id_fk", + "tableFrom": "sso_provider", + "tableTo": "organization", + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.subscription": { + "name": "subscription", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "plan": { + "name": "plan", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_subscription_id": { + "name": "stripe_subscription_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "period_start": { + "name": "period_start", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "period_end": { + "name": "period_end", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "cancel_at_period_end": { + "name": "cancel_at_period_end", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "seats": { + "name": "seats", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "trial_start": { + "name": "trial_start", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "trial_end": { + "name": "trial_end", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "json", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "subscription_reference_status_idx": { + "name": "subscription_reference_status_idx", + "columns": [ + { + "expression": "reference_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "check_enterprise_metadata": { + "name": "check_enterprise_metadata", + "value": "plan != 'enterprise' OR metadata IS NOT NULL" + } + }, + "isRLSEnabled": false + }, + "public.template_creators": { + "name": "template_creators", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "reference_type": { + "name": "reference_type", + "type": "template_creator_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "profile_image_url": { + "name": "profile_image_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "details": { + "name": "details", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "verified": { + "name": "verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "template_creators_reference_idx": { + "name": "template_creators_reference_idx", + "columns": [ + { + "expression": "reference_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "reference_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_creators_reference_id_idx": { + "name": "template_creators_reference_id_idx", + "columns": [ + { + "expression": "reference_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_creators_created_by_idx": { + "name": "template_creators_created_by_idx", + "columns": [ + { + "expression": "created_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "template_creators_created_by_user_id_fk": { + "name": "template_creators_created_by_user_id_fk", + "tableFrom": "template_creators", + "tableTo": "user", + "columnsFrom": ["created_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.template_stars": { + "name": "template_stars", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "template_id": { + "name": "template_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "starred_at": { + "name": "starred_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "template_stars_user_id_idx": { + "name": "template_stars_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_template_id_idx": { + "name": "template_stars_template_id_idx", + "columns": [ + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_user_template_idx": { + "name": "template_stars_user_template_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_template_user_idx": { + "name": "template_stars_template_user_idx", + "columns": [ + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_starred_at_idx": { + "name": "template_stars_starred_at_idx", + "columns": [ + { + "expression": "starred_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_template_starred_at_idx": { + "name": "template_stars_template_starred_at_idx", + "columns": [ + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "starred_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_user_template_unique": { + "name": "template_stars_user_template_unique", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "template_stars_user_id_user_id_fk": { + "name": "template_stars_user_id_user_id_fk", + "tableFrom": "template_stars", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "template_stars_template_id_templates_id_fk": { + "name": "template_stars_template_id_templates_id_fk", + "tableFrom": "template_stars", + "tableTo": "templates", + "columnsFrom": ["template_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.templates": { + "name": "templates", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "details": { + "name": "details", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "creator_id": { + "name": "creator_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "views": { + "name": "views", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "stars": { + "name": "stars", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "status": { + "name": "status", + "type": "template_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "tags": { + "name": "tags", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'::text[]" + }, + "required_credentials": { + "name": "required_credentials", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "state": { + "name": "state", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "templates_status_idx": { + "name": "templates_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_creator_id_idx": { + "name": "templates_creator_id_idx", + "columns": [ + { + "expression": "creator_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_views_idx": { + "name": "templates_views_idx", + "columns": [ + { + "expression": "views", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_stars_idx": { + "name": "templates_stars_idx", + "columns": [ + { + "expression": "stars", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_status_views_idx": { + "name": "templates_status_views_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "views", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_status_stars_idx": { + "name": "templates_status_stars_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "stars", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_created_at_idx": { + "name": "templates_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_updated_at_idx": { + "name": "templates_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "templates_workflow_id_workflow_id_fk": { + "name": "templates_workflow_id_workflow_id_fk", + "tableFrom": "templates", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "templates_creator_id_template_creators_id_fk": { + "name": "templates_creator_id_template_creators_id_fk", + "tableFrom": "templates", + "tableTo": "template_creators", + "columnsFrom": ["creator_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_super_user": { + "name": "is_super_user", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": ["email"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_stats": { + "name": "user_stats", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "total_manual_executions": { + "name": "total_manual_executions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_api_calls": { + "name": "total_api_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_webhook_triggers": { + "name": "total_webhook_triggers", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_scheduled_executions": { + "name": "total_scheduled_executions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_chat_executions": { + "name": "total_chat_executions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_tokens_used": { + "name": "total_tokens_used", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_cost": { + "name": "total_cost", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "current_usage_limit": { + "name": "current_usage_limit", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "default": "'10'" + }, + "usage_limit_updated_at": { + "name": "usage_limit_updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "current_period_cost": { + "name": "current_period_cost", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "last_period_cost": { + "name": "last_period_cost", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "default": "'0'" + }, + "billed_overage_this_period": { + "name": "billed_overage_this_period", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "pro_period_cost_snapshot": { + "name": "pro_period_cost_snapshot", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "default": "'0'" + }, + "credit_balance": { + "name": "credit_balance", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "total_copilot_cost": { + "name": "total_copilot_cost", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "current_period_copilot_cost": { + "name": "current_period_copilot_cost", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "last_period_copilot_cost": { + "name": "last_period_copilot_cost", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "default": "'0'" + }, + "total_copilot_tokens": { + "name": "total_copilot_tokens", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_copilot_calls": { + "name": "total_copilot_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "storage_used_bytes": { + "name": "storage_used_bytes", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_active": { + "name": "last_active", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "billing_blocked": { + "name": "billing_blocked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "billing_blocked_reason": { + "name": "billing_blocked_reason", + "type": "billing_blocked_reason", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "user_stats_user_id_user_id_fk": { + "name": "user_stats_user_id_user_id_fk", + "tableFrom": "user_stats", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_stats_user_id_unique": { + "name": "user_stats_user_id_unique", + "nullsNotDistinct": false, + "columns": ["user_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "verification_identifier_idx": { + "name": "verification_identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.waitlist": { + "name": "waitlist", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "waitlist_email_unique": { + "name": "waitlist_email_unique", + "nullsNotDistinct": false, + "columns": ["email"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.webhook": { + "name": "webhook", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "block_id": { + "name": "block_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider_config": { + "name": "provider_config", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "failed_count": { + "name": "failed_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "last_failed_at": { + "name": "last_failed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "path_idx": { + "name": "path_idx", + "columns": [ + { + "expression": "path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_webhook_on_workflow_id_block_id": { + "name": "idx_webhook_on_workflow_id_block_id", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "webhook_workflow_id_workflow_id_fk": { + "name": "webhook_workflow_id_workflow_id_fk", + "tableFrom": "webhook", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "webhook_block_id_workflow_blocks_id_fk": { + "name": "webhook_block_id_workflow_blocks_id_fk", + "tableFrom": "webhook", + "tableTo": "workflow_blocks", + "columnsFrom": ["block_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow": { + "name": "workflow", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "folder_id": { + "name": "folder_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'#3972F6'" + }, + "last_synced": { + "name": "last_synced", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "is_deployed": { + "name": "is_deployed", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "deployed_at": { + "name": "deployed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "run_count": { + "name": "run_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_run_at": { + "name": "last_run_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "variables": { + "name": "variables", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + } + }, + "indexes": { + "workflow_user_id_idx": { + "name": "workflow_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_workspace_id_idx": { + "name": "workflow_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_user_workspace_idx": { + "name": "workflow_user_workspace_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_user_id_user_id_fk": { + "name": "workflow_user_id_user_id_fk", + "tableFrom": "workflow", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_workspace_id_workspace_id_fk": { + "name": "workflow_workspace_id_workspace_id_fk", + "tableFrom": "workflow", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_folder_id_workflow_folder_id_fk": { + "name": "workflow_folder_id_workflow_folder_id_fk", + "tableFrom": "workflow", + "tableTo": "workflow_folder", + "columnsFrom": ["folder_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_blocks": { + "name": "workflow_blocks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "position_x": { + "name": "position_x", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "position_y": { + "name": "position_y", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "horizontal_handles": { + "name": "horizontal_handles", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "is_wide": { + "name": "is_wide", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "advanced_mode": { + "name": "advanced_mode", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "trigger_mode": { + "name": "trigger_mode", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "height": { + "name": "height", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "sub_blocks": { + "name": "sub_blocks", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "outputs": { + "name": "outputs", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_blocks_workflow_id_idx": { + "name": "workflow_blocks_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_blocks_workflow_id_workflow_id_fk": { + "name": "workflow_blocks_workflow_id_workflow_id_fk", + "tableFrom": "workflow_blocks", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_checkpoints": { + "name": "workflow_checkpoints", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chat_id": { + "name": "chat_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "message_id": { + "name": "message_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workflow_state": { + "name": "workflow_state", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_checkpoints_user_id_idx": { + "name": "workflow_checkpoints_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_workflow_id_idx": { + "name": "workflow_checkpoints_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_chat_id_idx": { + "name": "workflow_checkpoints_chat_id_idx", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_message_id_idx": { + "name": "workflow_checkpoints_message_id_idx", + "columns": [ + { + "expression": "message_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_user_workflow_idx": { + "name": "workflow_checkpoints_user_workflow_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_workflow_chat_idx": { + "name": "workflow_checkpoints_workflow_chat_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_created_at_idx": { + "name": "workflow_checkpoints_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_chat_created_at_idx": { + "name": "workflow_checkpoints_chat_created_at_idx", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_checkpoints_user_id_user_id_fk": { + "name": "workflow_checkpoints_user_id_user_id_fk", + "tableFrom": "workflow_checkpoints", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_checkpoints_workflow_id_workflow_id_fk": { + "name": "workflow_checkpoints_workflow_id_workflow_id_fk", + "tableFrom": "workflow_checkpoints", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_checkpoints_chat_id_copilot_chats_id_fk": { + "name": "workflow_checkpoints_chat_id_copilot_chats_id_fk", + "tableFrom": "workflow_checkpoints", + "tableTo": "copilot_chats", + "columnsFrom": ["chat_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_deployment_version": { + "name": "workflow_deployment_version", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "state": { + "name": "state", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "workflow_deployment_version_workflow_version_unique": { + "name": "workflow_deployment_version_workflow_version_unique", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "version", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_deployment_version_workflow_active_idx": { + "name": "workflow_deployment_version_workflow_active_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "is_active", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_deployment_version_created_at_idx": { + "name": "workflow_deployment_version_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_deployment_version_workflow_id_workflow_id_fk": { + "name": "workflow_deployment_version_workflow_id_workflow_id_fk", + "tableFrom": "workflow_deployment_version", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_edges": { + "name": "workflow_edges", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_block_id": { + "name": "source_block_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "target_block_id": { + "name": "target_block_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_handle": { + "name": "source_handle", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "target_handle": { + "name": "target_handle", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_edges_workflow_id_idx": { + "name": "workflow_edges_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_edges_workflow_source_idx": { + "name": "workflow_edges_workflow_source_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "source_block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_edges_workflow_target_idx": { + "name": "workflow_edges_workflow_target_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "target_block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_edges_workflow_id_workflow_id_fk": { + "name": "workflow_edges_workflow_id_workflow_id_fk", + "tableFrom": "workflow_edges", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_edges_source_block_id_workflow_blocks_id_fk": { + "name": "workflow_edges_source_block_id_workflow_blocks_id_fk", + "tableFrom": "workflow_edges", + "tableTo": "workflow_blocks", + "columnsFrom": ["source_block_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_edges_target_block_id_workflow_blocks_id_fk": { + "name": "workflow_edges_target_block_id_workflow_blocks_id_fk", + "tableFrom": "workflow_edges", + "tableTo": "workflow_blocks", + "columnsFrom": ["target_block_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_execution_logs": { + "name": "workflow_execution_logs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_id": { + "name": "execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state_snapshot_id": { + "name": "state_snapshot_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "deployment_version_id": { + "name": "deployment_version_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "level": { + "name": "level", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "trigger": { + "name": "trigger", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "total_duration_ms": { + "name": "total_duration_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "execution_data": { + "name": "execution_data", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "cost": { + "name": "cost", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "files": { + "name": "files", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_execution_logs_workflow_id_idx": { + "name": "workflow_execution_logs_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_state_snapshot_id_idx": { + "name": "workflow_execution_logs_state_snapshot_id_idx", + "columns": [ + { + "expression": "state_snapshot_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_deployment_version_id_idx": { + "name": "workflow_execution_logs_deployment_version_id_idx", + "columns": [ + { + "expression": "deployment_version_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_trigger_idx": { + "name": "workflow_execution_logs_trigger_idx", + "columns": [ + { + "expression": "trigger", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_level_idx": { + "name": "workflow_execution_logs_level_idx", + "columns": [ + { + "expression": "level", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_started_at_idx": { + "name": "workflow_execution_logs_started_at_idx", + "columns": [ + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_execution_id_unique": { + "name": "workflow_execution_logs_execution_id_unique", + "columns": [ + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_workflow_started_at_idx": { + "name": "workflow_execution_logs_workflow_started_at_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_execution_logs_workflow_id_workflow_id_fk": { + "name": "workflow_execution_logs_workflow_id_workflow_id_fk", + "tableFrom": "workflow_execution_logs", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_execution_logs_state_snapshot_id_workflow_execution_snapshots_id_fk": { + "name": "workflow_execution_logs_state_snapshot_id_workflow_execution_snapshots_id_fk", + "tableFrom": "workflow_execution_logs", + "tableTo": "workflow_execution_snapshots", + "columnsFrom": ["state_snapshot_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + }, + "workflow_execution_logs_deployment_version_id_workflow_deployment_version_id_fk": { + "name": "workflow_execution_logs_deployment_version_id_workflow_deployment_version_id_fk", + "tableFrom": "workflow_execution_logs", + "tableTo": "workflow_deployment_version", + "columnsFrom": ["deployment_version_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_execution_snapshots": { + "name": "workflow_execution_snapshots", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state_hash": { + "name": "state_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state_data": { + "name": "state_data", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_snapshots_workflow_id_idx": { + "name": "workflow_snapshots_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_snapshots_hash_idx": { + "name": "workflow_snapshots_hash_idx", + "columns": [ + { + "expression": "state_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_snapshots_workflow_hash_idx": { + "name": "workflow_snapshots_workflow_hash_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "state_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_snapshots_created_at_idx": { + "name": "workflow_snapshots_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_execution_snapshots_workflow_id_workflow_id_fk": { + "name": "workflow_execution_snapshots_workflow_id_workflow_id_fk", + "tableFrom": "workflow_execution_snapshots", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_folder": { + "name": "workflow_folder", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parent_id": { + "name": "parent_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'#6B7280'" + }, + "is_expanded": { + "name": "is_expanded", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_folder_user_idx": { + "name": "workflow_folder_user_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_folder_workspace_parent_idx": { + "name": "workflow_folder_workspace_parent_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_folder_parent_sort_idx": { + "name": "workflow_folder_parent_sort_idx", + "columns": [ + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "sort_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_folder_user_id_user_id_fk": { + "name": "workflow_folder_user_id_user_id_fk", + "tableFrom": "workflow_folder", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_folder_workspace_id_workspace_id_fk": { + "name": "workflow_folder_workspace_id_workspace_id_fk", + "tableFrom": "workflow_folder", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_schedule": { + "name": "workflow_schedule", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "block_id": { + "name": "block_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cron_expression": { + "name": "cron_expression", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "next_run_at": { + "name": "next_run_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_ran_at": { + "name": "last_ran_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_queued_at": { + "name": "last_queued_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "trigger_type": { + "name": "trigger_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "timezone": { + "name": "timezone", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'UTC'" + }, + "failed_count": { + "name": "failed_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "last_failed_at": { + "name": "last_failed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_schedule_workflow_block_unique": { + "name": "workflow_schedule_workflow_block_unique", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_schedule_workflow_id_workflow_id_fk": { + "name": "workflow_schedule_workflow_id_workflow_id_fk", + "tableFrom": "workflow_schedule", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_schedule_block_id_workflow_blocks_id_fk": { + "name": "workflow_schedule_block_id_workflow_blocks_id_fk", + "tableFrom": "workflow_schedule", + "tableTo": "workflow_blocks", + "columnsFrom": ["block_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_subflows": { + "name": "workflow_subflows", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_subflows_workflow_id_idx": { + "name": "workflow_subflows_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_subflows_workflow_type_idx": { + "name": "workflow_subflows_workflow_type_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_subflows_workflow_id_workflow_id_fk": { + "name": "workflow_subflows_workflow_id_workflow_id_fk", + "tableFrom": "workflow_subflows", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace": { + "name": "workspace", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "owner_id": { + "name": "owner_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "billed_account_user_id": { + "name": "billed_account_user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "allow_personal_api_keys": { + "name": "allow_personal_api_keys", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workspace_owner_id_user_id_fk": { + "name": "workspace_owner_id_user_id_fk", + "tableFrom": "workspace", + "tableTo": "user", + "columnsFrom": ["owner_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_billed_account_user_id_user_id_fk": { + "name": "workspace_billed_account_user_id_user_id_fk", + "tableFrom": "workspace", + "tableTo": "user", + "columnsFrom": ["billed_account_user_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_environment": { + "name": "workspace_environment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "variables": { + "name": "variables", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_environment_workspace_unique": { + "name": "workspace_environment_workspace_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_environment_workspace_id_workspace_id_fk": { + "name": "workspace_environment_workspace_id_workspace_id_fk", + "tableFrom": "workspace_environment", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_file": { + "name": "workspace_file", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "uploaded_by": { + "name": "uploaded_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "uploaded_at": { + "name": "uploaded_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_file_workspace_id_idx": { + "name": "workspace_file_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_file_key_idx": { + "name": "workspace_file_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_file_workspace_id_workspace_id_fk": { + "name": "workspace_file_workspace_id_workspace_id_fk", + "tableFrom": "workspace_file", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_file_uploaded_by_user_id_fk": { + "name": "workspace_file_uploaded_by_user_id_fk", + "tableFrom": "workspace_file", + "tableTo": "user", + "columnsFrom": ["uploaded_by"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_file_key_unique": { + "name": "workspace_file_key_unique", + "nullsNotDistinct": false, + "columns": ["key"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_files": { + "name": "workspace_files", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "context": { + "name": "context", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "original_name": { + "name": "original_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content_type": { + "name": "content_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "uploaded_at": { + "name": "uploaded_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_files_key_idx": { + "name": "workspace_files_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_user_id_idx": { + "name": "workspace_files_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_workspace_id_idx": { + "name": "workspace_files_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_context_idx": { + "name": "workspace_files_context_idx", + "columns": [ + { + "expression": "context", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_files_user_id_user_id_fk": { + "name": "workspace_files_user_id_user_id_fk", + "tableFrom": "workspace_files", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_files_workspace_id_workspace_id_fk": { + "name": "workspace_files_workspace_id_workspace_id_fk", + "tableFrom": "workspace_files", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_files_key_unique": { + "name": "workspace_files_key_unique", + "nullsNotDistinct": false, + "columns": ["key"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_invitation": { + "name": "workspace_invitation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'member'" + }, + "status": { + "name": "status", + "type": "workspace_invitation_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "permissions": { + "name": "permissions", + "type": "permission_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'admin'" + }, + "org_invitation_id": { + "name": "org_invitation_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workspace_invitation_workspace_id_workspace_id_fk": { + "name": "workspace_invitation_workspace_id_workspace_id_fk", + "tableFrom": "workspace_invitation", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_invitation_inviter_id_user_id_fk": { + "name": "workspace_invitation_inviter_id_user_id_fk", + "tableFrom": "workspace_invitation", + "tableTo": "user", + "columnsFrom": ["inviter_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_invitation_token_unique": { + "name": "workspace_invitation_token_unique", + "nullsNotDistinct": false, + "columns": ["token"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_notification_delivery": { + "name": "workspace_notification_delivery", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "subscription_id": { + "name": "subscription_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_id": { + "name": "execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "notification_delivery_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "attempts": { + "name": "attempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_attempt_at": { + "name": "last_attempt_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "next_attempt_at": { + "name": "next_attempt_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "response_status": { + "name": "response_status", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "response_body": { + "name": "response_body", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_notification_delivery_subscription_id_idx": { + "name": "workspace_notification_delivery_subscription_id_idx", + "columns": [ + { + "expression": "subscription_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_notification_delivery_execution_id_idx": { + "name": "workspace_notification_delivery_execution_id_idx", + "columns": [ + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_notification_delivery_status_idx": { + "name": "workspace_notification_delivery_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_notification_delivery_next_attempt_idx": { + "name": "workspace_notification_delivery_next_attempt_idx", + "columns": [ + { + "expression": "next_attempt_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_notification_delivery_subscription_id_workspace_notification_subscription_id_fk": { + "name": "workspace_notification_delivery_subscription_id_workspace_notification_subscription_id_fk", + "tableFrom": "workspace_notification_delivery", + "tableTo": "workspace_notification_subscription", + "columnsFrom": ["subscription_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_notification_delivery_workflow_id_workflow_id_fk": { + "name": "workspace_notification_delivery_workflow_id_workflow_id_fk", + "tableFrom": "workspace_notification_delivery", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_notification_subscription": { + "name": "workspace_notification_subscription", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "notification_type": { + "name": "notification_type", + "type": "notification_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "workflow_ids": { + "name": "workflow_ids", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'::text[]" + }, + "all_workflows": { + "name": "all_workflows", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "level_filter": { + "name": "level_filter", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY['info', 'error']::text[]" + }, + "trigger_filter": { + "name": "trigger_filter", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY['api', 'webhook', 'schedule', 'manual', 'chat']::text[]" + }, + "include_final_output": { + "name": "include_final_output", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "include_trace_spans": { + "name": "include_trace_spans", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "include_rate_limits": { + "name": "include_rate_limits", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "include_usage_data": { + "name": "include_usage_data", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "webhook_config": { + "name": "webhook_config", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "email_recipients": { + "name": "email_recipients", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "slack_config": { + "name": "slack_config", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "alert_config": { + "name": "alert_config", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "last_alert_at": { + "name": "last_alert_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_notification_workspace_id_idx": { + "name": "workspace_notification_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_notification_active_idx": { + "name": "workspace_notification_active_idx", + "columns": [ + { + "expression": "active", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_notification_type_idx": { + "name": "workspace_notification_type_idx", + "columns": [ + { + "expression": "notification_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_notification_subscription_workspace_id_workspace_id_fk": { + "name": "workspace_notification_subscription_workspace_id_workspace_id_fk", + "tableFrom": "workspace_notification_subscription", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_notification_subscription_created_by_user_id_fk": { + "name": "workspace_notification_subscription_created_by_user_id_fk", + "tableFrom": "workspace_notification_subscription", + "tableTo": "user", + "columnsFrom": ["created_by"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.billing_blocked_reason": { + "name": "billing_blocked_reason", + "schema": "public", + "values": ["payment_failed", "dispute"] + }, + "public.notification_delivery_status": { + "name": "notification_delivery_status", + "schema": "public", + "values": ["pending", "in_progress", "success", "failed"] + }, + "public.notification_type": { + "name": "notification_type", + "schema": "public", + "values": ["webhook", "email", "slack"] + }, + "public.permission_type": { + "name": "permission_type", + "schema": "public", + "values": ["admin", "write", "read"] + }, + "public.template_creator_type": { + "name": "template_creator_type", + "schema": "public", + "values": ["user", "organization"] + }, + "public.template_status": { + "name": "template_status", + "schema": "public", + "values": ["pending", "approved", "rejected"] + }, + "public.workspace_invitation_status": { + "name": "workspace_invitation_status", + "schema": "public", + "values": ["pending", "accepted", "rejected", "cancelled"] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/packages/db/migrations/meta/0124_snapshot.json b/packages/db/migrations/meta/0124_snapshot.json new file mode 100644 index 0000000000..46103bd0dd --- /dev/null +++ b/packages/db/migrations/meta/0124_snapshot.json @@ -0,0 +1,8363 @@ +{ + "id": "762e8c60-cb46-4f0c-9c51-ba74d413ad95", + "prevId": "1be6ebb3-fe8a-4abd-9f4d-cfb8341f5319", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "account_user_id_idx": { + "name": "account_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_account_on_account_id_provider_id": { + "name": "idx_account_on_account_id_provider_id", + "columns": [ + { + "expression": "account_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "account_user_provider_account_unique": { + "name": "account_user_provider_account_unique", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "account_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.api_key": { + "name": "api_key", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'personal'" + }, + "last_used": { + "name": "last_used", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "api_key_user_id_user_id_fk": { + "name": "api_key_user_id_user_id_fk", + "tableFrom": "api_key", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "api_key_workspace_id_workspace_id_fk": { + "name": "api_key_workspace_id_workspace_id_fk", + "tableFrom": "api_key", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "api_key_created_by_user_id_fk": { + "name": "api_key_created_by_user_id_fk", + "tableFrom": "api_key", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "api_key_key_unique": { + "name": "api_key_key_unique", + "nullsNotDistinct": false, + "columns": [ + "key" + ] + } + }, + "policies": {}, + "checkConstraints": { + "workspace_type_check": { + "name": "workspace_type_check", + "value": "(type = 'workspace' AND workspace_id IS NOT NULL) OR (type = 'personal' AND workspace_id IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.chat": { + "name": "chat", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "customizations": { + "name": "customizations", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "auth_type": { + "name": "auth_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'public'" + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "allowed_emails": { + "name": "allowed_emails", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'[]'" + }, + "output_configs": { + "name": "output_configs", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'[]'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "identifier_idx": { + "name": "identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "chat_workflow_id_workflow_id_fk": { + "name": "chat_workflow_id_workflow_id_fk", + "tableFrom": "chat", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "chat_user_id_user_id_fk": { + "name": "chat_user_id_user_id_fk", + "tableFrom": "chat", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.copilot_chats": { + "name": "copilot_chats", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "messages": { + "name": "messages", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'claude-3-7-sonnet-latest'" + }, + "conversation_id": { + "name": "conversation_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "preview_yaml": { + "name": "preview_yaml", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "plan_artifact": { + "name": "plan_artifact", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "copilot_chats_user_id_idx": { + "name": "copilot_chats_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_workflow_id_idx": { + "name": "copilot_chats_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_user_workflow_idx": { + "name": "copilot_chats_user_workflow_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_created_at_idx": { + "name": "copilot_chats_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_updated_at_idx": { + "name": "copilot_chats_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "copilot_chats_user_id_user_id_fk": { + "name": "copilot_chats_user_id_user_id_fk", + "tableFrom": "copilot_chats", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "copilot_chats_workflow_id_workflow_id_fk": { + "name": "copilot_chats_workflow_id_workflow_id_fk", + "tableFrom": "copilot_chats", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.copilot_feedback": { + "name": "copilot_feedback", + "schema": "", + "columns": { + "feedback_id": { + "name": "feedback_id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chat_id": { + "name": "chat_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_query": { + "name": "user_query", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "agent_response": { + "name": "agent_response", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "is_positive": { + "name": "is_positive", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "feedback": { + "name": "feedback", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workflow_yaml": { + "name": "workflow_yaml", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "copilot_feedback_user_id_idx": { + "name": "copilot_feedback_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_feedback_chat_id_idx": { + "name": "copilot_feedback_chat_id_idx", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_feedback_user_chat_idx": { + "name": "copilot_feedback_user_chat_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_feedback_is_positive_idx": { + "name": "copilot_feedback_is_positive_idx", + "columns": [ + { + "expression": "is_positive", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_feedback_created_at_idx": { + "name": "copilot_feedback_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "copilot_feedback_user_id_user_id_fk": { + "name": "copilot_feedback_user_id_user_id_fk", + "tableFrom": "copilot_feedback", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "copilot_feedback_chat_id_copilot_chats_id_fk": { + "name": "copilot_feedback_chat_id_copilot_chats_id_fk", + "tableFrom": "copilot_feedback", + "tableTo": "copilot_chats", + "columnsFrom": [ + "chat_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.custom_tools": { + "name": "custom_tools", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "schema": { + "name": "schema", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "code": { + "name": "code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "custom_tools_workspace_id_idx": { + "name": "custom_tools_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "custom_tools_workspace_title_unique": { + "name": "custom_tools_workspace_title_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "title", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "custom_tools_workspace_id_workspace_id_fk": { + "name": "custom_tools_workspace_id_workspace_id_fk", + "tableFrom": "custom_tools", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "custom_tools_user_id_user_id_fk": { + "name": "custom_tools_user_id_user_id_fk", + "tableFrom": "custom_tools", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.docs_embeddings": { + "name": "docs_embeddings", + "schema": "", + "columns": { + "chunk_id": { + "name": "chunk_id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "chunk_text": { + "name": "chunk_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_document": { + "name": "source_document", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_link": { + "name": "source_link", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "header_text": { + "name": "header_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "header_level": { + "name": "header_level", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "token_count": { + "name": "token_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "embedding": { + "name": "embedding", + "type": "vector(1536)", + "primaryKey": false, + "notNull": true + }, + "embedding_model": { + "name": "embedding_model", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text-embedding-3-small'" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "chunk_text_tsv": { + "name": "chunk_text_tsv", + "type": "tsvector", + "primaryKey": false, + "notNull": false, + "generated": { + "as": "to_tsvector('english', \"docs_embeddings\".\"chunk_text\")", + "type": "stored" + } + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "docs_emb_source_document_idx": { + "name": "docs_emb_source_document_idx", + "columns": [ + { + "expression": "source_document", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_emb_header_level_idx": { + "name": "docs_emb_header_level_idx", + "columns": [ + { + "expression": "header_level", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_emb_source_header_idx": { + "name": "docs_emb_source_header_idx", + "columns": [ + { + "expression": "source_document", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "header_level", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_emb_model_idx": { + "name": "docs_emb_model_idx", + "columns": [ + { + "expression": "embedding_model", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_emb_created_at_idx": { + "name": "docs_emb_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_embedding_vector_hnsw_idx": { + "name": "docs_embedding_vector_hnsw_idx", + "columns": [ + { + "expression": "embedding", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "vector_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": { + "m": 16, + "ef_construction": 64 + } + }, + "docs_emb_metadata_gin_idx": { + "name": "docs_emb_metadata_gin_idx", + "columns": [ + { + "expression": "metadata", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + }, + "docs_emb_chunk_text_fts_idx": { + "name": "docs_emb_chunk_text_fts_idx", + "columns": [ + { + "expression": "chunk_text_tsv", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "docs_embedding_not_null_check": { + "name": "docs_embedding_not_null_check", + "value": "\"embedding\" IS NOT NULL" + }, + "docs_header_level_check": { + "name": "docs_header_level_check", + "value": "\"header_level\" >= 1 AND \"header_level\" <= 6" + } + }, + "isRLSEnabled": false + }, + "public.document": { + "name": "document", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "filename": { + "name": "filename", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "file_url": { + "name": "file_url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "file_size": { + "name": "file_size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "mime_type": { + "name": "mime_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chunk_count": { + "name": "chunk_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "token_count": { + "name": "token_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "character_count": { + "name": "character_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "processing_status": { + "name": "processing_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "processing_started_at": { + "name": "processing_started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "processing_completed_at": { + "name": "processing_completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "processing_error": { + "name": "processing_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "tag1": { + "name": "tag1", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag2": { + "name": "tag2", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag3": { + "name": "tag3", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag4": { + "name": "tag4", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag5": { + "name": "tag5", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag6": { + "name": "tag6", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag7": { + "name": "tag7", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "uploaded_at": { + "name": "uploaded_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "doc_kb_id_idx": { + "name": "doc_kb_id_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_filename_idx": { + "name": "doc_filename_idx", + "columns": [ + { + "expression": "filename", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_processing_status_idx": { + "name": "doc_processing_status_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "processing_status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag1_idx": { + "name": "doc_tag1_idx", + "columns": [ + { + "expression": "tag1", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag2_idx": { + "name": "doc_tag2_idx", + "columns": [ + { + "expression": "tag2", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag3_idx": { + "name": "doc_tag3_idx", + "columns": [ + { + "expression": "tag3", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag4_idx": { + "name": "doc_tag4_idx", + "columns": [ + { + "expression": "tag4", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag5_idx": { + "name": "doc_tag5_idx", + "columns": [ + { + "expression": "tag5", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag6_idx": { + "name": "doc_tag6_idx", + "columns": [ + { + "expression": "tag6", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag7_idx": { + "name": "doc_tag7_idx", + "columns": [ + { + "expression": "tag7", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "document_knowledge_base_id_knowledge_base_id_fk": { + "name": "document_knowledge_base_id_knowledge_base_id_fk", + "tableFrom": "document", + "tableTo": "knowledge_base", + "columnsFrom": [ + "knowledge_base_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.embedding": { + "name": "embedding", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "document_id": { + "name": "document_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chunk_index": { + "name": "chunk_index", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "chunk_hash": { + "name": "chunk_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content_length": { + "name": "content_length", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "token_count": { + "name": "token_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "embedding": { + "name": "embedding", + "type": "vector(1536)", + "primaryKey": false, + "notNull": false + }, + "embedding_model": { + "name": "embedding_model", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text-embedding-3-small'" + }, + "start_offset": { + "name": "start_offset", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "end_offset": { + "name": "end_offset", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "tag1": { + "name": "tag1", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag2": { + "name": "tag2", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag3": { + "name": "tag3", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag4": { + "name": "tag4", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag5": { + "name": "tag5", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag6": { + "name": "tag6", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag7": { + "name": "tag7", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "content_tsv": { + "name": "content_tsv", + "type": "tsvector", + "primaryKey": false, + "notNull": false, + "generated": { + "as": "to_tsvector('english', \"embedding\".\"content\")", + "type": "stored" + } + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "emb_kb_id_idx": { + "name": "emb_kb_id_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_doc_id_idx": { + "name": "emb_doc_id_idx", + "columns": [ + { + "expression": "document_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_doc_chunk_idx": { + "name": "emb_doc_chunk_idx", + "columns": [ + { + "expression": "document_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "chunk_index", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_kb_model_idx": { + "name": "emb_kb_model_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "embedding_model", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_kb_enabled_idx": { + "name": "emb_kb_enabled_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_doc_enabled_idx": { + "name": "emb_doc_enabled_idx", + "columns": [ + { + "expression": "document_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "embedding_vector_hnsw_idx": { + "name": "embedding_vector_hnsw_idx", + "columns": [ + { + "expression": "embedding", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "vector_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": { + "m": 16, + "ef_construction": 64 + } + }, + "emb_tag1_idx": { + "name": "emb_tag1_idx", + "columns": [ + { + "expression": "tag1", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag2_idx": { + "name": "emb_tag2_idx", + "columns": [ + { + "expression": "tag2", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag3_idx": { + "name": "emb_tag3_idx", + "columns": [ + { + "expression": "tag3", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag4_idx": { + "name": "emb_tag4_idx", + "columns": [ + { + "expression": "tag4", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag5_idx": { + "name": "emb_tag5_idx", + "columns": [ + { + "expression": "tag5", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag6_idx": { + "name": "emb_tag6_idx", + "columns": [ + { + "expression": "tag6", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag7_idx": { + "name": "emb_tag7_idx", + "columns": [ + { + "expression": "tag7", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_content_fts_idx": { + "name": "emb_content_fts_idx", + "columns": [ + { + "expression": "content_tsv", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + } + }, + "foreignKeys": { + "embedding_knowledge_base_id_knowledge_base_id_fk": { + "name": "embedding_knowledge_base_id_knowledge_base_id_fk", + "tableFrom": "embedding", + "tableTo": "knowledge_base", + "columnsFrom": [ + "knowledge_base_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "embedding_document_id_document_id_fk": { + "name": "embedding_document_id_document_id_fk", + "tableFrom": "embedding", + "tableTo": "document", + "columnsFrom": [ + "document_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "embedding_not_null_check": { + "name": "embedding_not_null_check", + "value": "\"embedding\" IS NOT NULL" + } + }, + "isRLSEnabled": false + }, + "public.environment": { + "name": "environment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "variables": { + "name": "variables", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "environment_user_id_user_id_fk": { + "name": "environment_user_id_user_id_fk", + "tableFrom": "environment", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "environment_user_id_unique": { + "name": "environment_user_id_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.idempotency_key": { + "name": "idempotency_key", + "schema": "", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "namespace": { + "name": "namespace", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'default'" + }, + "result": { + "name": "result", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "idempotency_key_namespace_unique": { + "name": "idempotency_key_namespace_unique", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "namespace", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idempotency_key_created_at_idx": { + "name": "idempotency_key_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idempotency_key_namespace_idx": { + "name": "idempotency_key_namespace_idx", + "columns": [ + { + "expression": "namespace", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.invitation": { + "name": "invitation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "invitation_email_idx": { + "name": "invitation_email_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "invitation_organization_id_idx": { + "name": "invitation_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "invitation_inviter_id_user_id_fk": { + "name": "invitation_inviter_id_user_id_fk", + "tableFrom": "invitation", + "tableTo": "user", + "columnsFrom": [ + "inviter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "invitation_organization_id_organization_id_fk": { + "name": "invitation_organization_id_organization_id_fk", + "tableFrom": "invitation", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knowledge_base": { + "name": "knowledge_base", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "token_count": { + "name": "token_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "embedding_model": { + "name": "embedding_model", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text-embedding-3-small'" + }, + "embedding_dimension": { + "name": "embedding_dimension", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1536 + }, + "chunking_config": { + "name": "chunking_config", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{\"maxSize\": 1024, \"minSize\": 1, \"overlap\": 200}'" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "kb_user_id_idx": { + "name": "kb_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_workspace_id_idx": { + "name": "kb_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_user_workspace_idx": { + "name": "kb_user_workspace_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_deleted_at_idx": { + "name": "kb_deleted_at_idx", + "columns": [ + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knowledge_base_user_id_user_id_fk": { + "name": "knowledge_base_user_id_user_id_fk", + "tableFrom": "knowledge_base", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knowledge_base_workspace_id_workspace_id_fk": { + "name": "knowledge_base_workspace_id_workspace_id_fk", + "tableFrom": "knowledge_base", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knowledge_base_tag_definitions": { + "name": "knowledge_base_tag_definitions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tag_slot": { + "name": "tag_slot", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "field_type": { + "name": "field_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "kb_tag_definitions_kb_slot_idx": { + "name": "kb_tag_definitions_kb_slot_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tag_slot", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_tag_definitions_kb_display_name_idx": { + "name": "kb_tag_definitions_kb_display_name_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "display_name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_tag_definitions_kb_id_idx": { + "name": "kb_tag_definitions_kb_id_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knowledge_base_tag_definitions_knowledge_base_id_knowledge_base_id_fk": { + "name": "knowledge_base_tag_definitions_knowledge_base_id_knowledge_base_id_fk", + "tableFrom": "knowledge_base_tag_definitions", + "tableTo": "knowledge_base", + "columnsFrom": [ + "knowledge_base_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.mcp_servers": { + "name": "mcp_servers", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "transport": { + "name": "transport", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "headers": { + "name": "headers", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "timeout": { + "name": "timeout", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 30000 + }, + "retries": { + "name": "retries", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 3 + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "last_connected": { + "name": "last_connected", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "connection_status": { + "name": "connection_status", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'disconnected'" + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status_config": { + "name": "status_config", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "tool_count": { + "name": "tool_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "last_tools_refresh": { + "name": "last_tools_refresh", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "total_requests": { + "name": "total_requests", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "last_used": { + "name": "last_used", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "mcp_servers_workspace_enabled_idx": { + "name": "mcp_servers_workspace_enabled_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "mcp_servers_workspace_deleted_idx": { + "name": "mcp_servers_workspace_deleted_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "mcp_servers_workspace_id_workspace_id_fk": { + "name": "mcp_servers_workspace_id_workspace_id_fk", + "tableFrom": "mcp_servers", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mcp_servers_created_by_user_id_fk": { + "name": "mcp_servers_created_by_user_id_fk", + "tableFrom": "mcp_servers", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.member": { + "name": "member", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "member_user_id_idx": { + "name": "member_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "member_organization_id_idx": { + "name": "member_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "member_user_id_user_id_fk": { + "name": "member_user_id_user_id_fk", + "tableFrom": "member", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "member_organization_id_organization_id_fk": { + "name": "member_organization_id_organization_id_fk", + "tableFrom": "member", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.memory": { + "name": "memory", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "memory_key_idx": { + "name": "memory_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "memory_workflow_idx": { + "name": "memory_workflow_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "memory_workflow_key_idx": { + "name": "memory_workflow_key_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "memory_workflow_id_workflow_id_fk": { + "name": "memory_workflow_id_workflow_id_fk", + "tableFrom": "memory", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organization": { + "name": "organization", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "logo": { + "name": "logo", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "org_usage_limit": { + "name": "org_usage_limit", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "storage_used_bytes": { + "name": "storage_used_bytes", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "departed_member_usage": { + "name": "departed_member_usage", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "credit_balance": { + "name": "credit_balance", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.paused_executions": { + "name": "paused_executions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_id": { + "name": "execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_snapshot": { + "name": "execution_snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "pause_points": { + "name": "pause_points", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "total_pause_count": { + "name": "total_pause_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "resumed_count": { + "name": "resumed_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'paused'" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "paused_at": { + "name": "paused_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "paused_executions_workflow_id_idx": { + "name": "paused_executions_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "paused_executions_status_idx": { + "name": "paused_executions_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "paused_executions_execution_id_unique": { + "name": "paused_executions_execution_id_unique", + "columns": [ + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "paused_executions_workflow_id_workflow_id_fk": { + "name": "paused_executions_workflow_id_workflow_id_fk", + "tableFrom": "paused_executions", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.permissions": { + "name": "permissions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "permission_type": { + "name": "permission_type", + "type": "permission_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "permissions_user_id_idx": { + "name": "permissions_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_entity_idx": { + "name": "permissions_entity_idx", + "columns": [ + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_user_entity_type_idx": { + "name": "permissions_user_entity_type_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_user_entity_permission_idx": { + "name": "permissions_user_entity_permission_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "permission_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_user_entity_idx": { + "name": "permissions_user_entity_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_unique_constraint": { + "name": "permissions_unique_constraint", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "permissions_user_id_user_id_fk": { + "name": "permissions_user_id_user_id_fk", + "tableFrom": "permissions", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.rate_limit_bucket": { + "name": "rate_limit_bucket", + "schema": "", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tokens": { + "name": "tokens", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "last_refill_at": { + "name": "last_refill_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.resume_queue": { + "name": "resume_queue", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "paused_execution_id": { + "name": "paused_execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parent_execution_id": { + "name": "parent_execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "new_execution_id": { + "name": "new_execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "context_id": { + "name": "context_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resume_input": { + "name": "resume_input", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "queued_at": { + "name": "queued_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "claimed_at": { + "name": "claimed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "failure_reason": { + "name": "failure_reason", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "resume_queue_parent_status_idx": { + "name": "resume_queue_parent_status_idx", + "columns": [ + { + "expression": "parent_execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "queued_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "resume_queue_new_execution_idx": { + "name": "resume_queue_new_execution_idx", + "columns": [ + { + "expression": "new_execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resume_queue_paused_execution_id_paused_executions_id_fk": { + "name": "resume_queue_paused_execution_id_paused_executions_id_fk", + "tableFrom": "resume_queue", + "tableTo": "paused_executions", + "columnsFrom": [ + "paused_execution_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "active_organization_id": { + "name": "active_organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "session_user_id_idx": { + "name": "session_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "session_token_idx": { + "name": "session_token_idx", + "columns": [ + { + "expression": "token", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "session_active_organization_id_organization_id_fk": { + "name": "session_active_organization_id_organization_id_fk", + "tableFrom": "session", + "tableTo": "organization", + "columnsFrom": [ + "active_organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.settings": { + "name": "settings", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "theme": { + "name": "theme", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'system'" + }, + "auto_connect": { + "name": "auto_connect", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "telemetry_enabled": { + "name": "telemetry_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "email_preferences": { + "name": "email_preferences", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "billing_usage_notifications_enabled": { + "name": "billing_usage_notifications_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "show_training_controls": { + "name": "show_training_controls", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "super_user_mode_enabled": { + "name": "super_user_mode_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "error_notifications_enabled": { + "name": "error_notifications_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "copilot_enabled_models": { + "name": "copilot_enabled_models", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "copilot_auto_allowed_tools": { + "name": "copilot_auto_allowed_tools", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "settings_user_id_user_id_fk": { + "name": "settings_user_id_user_id_fk", + "tableFrom": "settings", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "settings_user_id_unique": { + "name": "settings_user_id_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sso_provider": { + "name": "sso_provider", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "issuer": { + "name": "issuer", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "domain": { + "name": "domain", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "oidc_config": { + "name": "oidc_config", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "saml_config": { + "name": "saml_config", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "sso_provider_provider_id_idx": { + "name": "sso_provider_provider_id_idx", + "columns": [ + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sso_provider_domain_idx": { + "name": "sso_provider_domain_idx", + "columns": [ + { + "expression": "domain", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sso_provider_user_id_idx": { + "name": "sso_provider_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sso_provider_organization_id_idx": { + "name": "sso_provider_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "sso_provider_user_id_user_id_fk": { + "name": "sso_provider_user_id_user_id_fk", + "tableFrom": "sso_provider", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "sso_provider_organization_id_organization_id_fk": { + "name": "sso_provider_organization_id_organization_id_fk", + "tableFrom": "sso_provider", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.subscription": { + "name": "subscription", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "plan": { + "name": "plan", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_subscription_id": { + "name": "stripe_subscription_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "period_start": { + "name": "period_start", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "period_end": { + "name": "period_end", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "cancel_at_period_end": { + "name": "cancel_at_period_end", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "seats": { + "name": "seats", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "trial_start": { + "name": "trial_start", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "trial_end": { + "name": "trial_end", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "json", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "subscription_reference_status_idx": { + "name": "subscription_reference_status_idx", + "columns": [ + { + "expression": "reference_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "check_enterprise_metadata": { + "name": "check_enterprise_metadata", + "value": "plan != 'enterprise' OR metadata IS NOT NULL" + } + }, + "isRLSEnabled": false + }, + "public.template_creators": { + "name": "template_creators", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "reference_type": { + "name": "reference_type", + "type": "template_creator_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "profile_image_url": { + "name": "profile_image_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "details": { + "name": "details", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "verified": { + "name": "verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "template_creators_reference_idx": { + "name": "template_creators_reference_idx", + "columns": [ + { + "expression": "reference_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "reference_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_creators_reference_id_idx": { + "name": "template_creators_reference_id_idx", + "columns": [ + { + "expression": "reference_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_creators_created_by_idx": { + "name": "template_creators_created_by_idx", + "columns": [ + { + "expression": "created_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "template_creators_created_by_user_id_fk": { + "name": "template_creators_created_by_user_id_fk", + "tableFrom": "template_creators", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.template_stars": { + "name": "template_stars", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "template_id": { + "name": "template_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "starred_at": { + "name": "starred_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "template_stars_user_id_idx": { + "name": "template_stars_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_template_id_idx": { + "name": "template_stars_template_id_idx", + "columns": [ + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_user_template_idx": { + "name": "template_stars_user_template_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_template_user_idx": { + "name": "template_stars_template_user_idx", + "columns": [ + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_starred_at_idx": { + "name": "template_stars_starred_at_idx", + "columns": [ + { + "expression": "starred_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_template_starred_at_idx": { + "name": "template_stars_template_starred_at_idx", + "columns": [ + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "starred_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_user_template_unique": { + "name": "template_stars_user_template_unique", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "template_stars_user_id_user_id_fk": { + "name": "template_stars_user_id_user_id_fk", + "tableFrom": "template_stars", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "template_stars_template_id_templates_id_fk": { + "name": "template_stars_template_id_templates_id_fk", + "tableFrom": "template_stars", + "tableTo": "templates", + "columnsFrom": [ + "template_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.templates": { + "name": "templates", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "details": { + "name": "details", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "creator_id": { + "name": "creator_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "views": { + "name": "views", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "stars": { + "name": "stars", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "status": { + "name": "status", + "type": "template_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "tags": { + "name": "tags", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'::text[]" + }, + "required_credentials": { + "name": "required_credentials", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "state": { + "name": "state", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "templates_status_idx": { + "name": "templates_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_creator_id_idx": { + "name": "templates_creator_id_idx", + "columns": [ + { + "expression": "creator_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_views_idx": { + "name": "templates_views_idx", + "columns": [ + { + "expression": "views", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_stars_idx": { + "name": "templates_stars_idx", + "columns": [ + { + "expression": "stars", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_status_views_idx": { + "name": "templates_status_views_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "views", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_status_stars_idx": { + "name": "templates_status_stars_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "stars", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_created_at_idx": { + "name": "templates_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_updated_at_idx": { + "name": "templates_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "templates_workflow_id_workflow_id_fk": { + "name": "templates_workflow_id_workflow_id_fk", + "tableFrom": "templates", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "templates_creator_id_template_creators_id_fk": { + "name": "templates_creator_id_template_creators_id_fk", + "tableFrom": "templates", + "tableTo": "template_creators", + "columnsFrom": [ + "creator_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_super_user": { + "name": "is_super_user", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_stats": { + "name": "user_stats", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "total_manual_executions": { + "name": "total_manual_executions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_api_calls": { + "name": "total_api_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_webhook_triggers": { + "name": "total_webhook_triggers", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_scheduled_executions": { + "name": "total_scheduled_executions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_chat_executions": { + "name": "total_chat_executions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_tokens_used": { + "name": "total_tokens_used", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_cost": { + "name": "total_cost", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "current_usage_limit": { + "name": "current_usage_limit", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "default": "'10'" + }, + "usage_limit_updated_at": { + "name": "usage_limit_updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "current_period_cost": { + "name": "current_period_cost", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "last_period_cost": { + "name": "last_period_cost", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "default": "'0'" + }, + "billed_overage_this_period": { + "name": "billed_overage_this_period", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "pro_period_cost_snapshot": { + "name": "pro_period_cost_snapshot", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "default": "'0'" + }, + "credit_balance": { + "name": "credit_balance", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "total_copilot_cost": { + "name": "total_copilot_cost", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "current_period_copilot_cost": { + "name": "current_period_copilot_cost", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "last_period_copilot_cost": { + "name": "last_period_copilot_cost", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "default": "'0'" + }, + "total_copilot_tokens": { + "name": "total_copilot_tokens", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_copilot_calls": { + "name": "total_copilot_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "storage_used_bytes": { + "name": "storage_used_bytes", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_active": { + "name": "last_active", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "billing_blocked": { + "name": "billing_blocked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "billing_blocked_reason": { + "name": "billing_blocked_reason", + "type": "billing_blocked_reason", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "user_stats_user_id_user_id_fk": { + "name": "user_stats_user_id_user_id_fk", + "tableFrom": "user_stats", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_stats_user_id_unique": { + "name": "user_stats_user_id_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "verification_identifier_idx": { + "name": "verification_identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.waitlist": { + "name": "waitlist", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "waitlist_email_unique": { + "name": "waitlist_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.webhook": { + "name": "webhook", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "block_id": { + "name": "block_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider_config": { + "name": "provider_config", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "failed_count": { + "name": "failed_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "last_failed_at": { + "name": "last_failed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "path_idx": { + "name": "path_idx", + "columns": [ + { + "expression": "path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_webhook_on_workflow_id_block_id": { + "name": "idx_webhook_on_workflow_id_block_id", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "webhook_workflow_id_workflow_id_fk": { + "name": "webhook_workflow_id_workflow_id_fk", + "tableFrom": "webhook", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "webhook_block_id_workflow_blocks_id_fk": { + "name": "webhook_block_id_workflow_blocks_id_fk", + "tableFrom": "webhook", + "tableTo": "workflow_blocks", + "columnsFrom": [ + "block_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow": { + "name": "workflow", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "folder_id": { + "name": "folder_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'#3972F6'" + }, + "last_synced": { + "name": "last_synced", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "is_deployed": { + "name": "is_deployed", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "deployed_at": { + "name": "deployed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "run_count": { + "name": "run_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_run_at": { + "name": "last_run_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "variables": { + "name": "variables", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + } + }, + "indexes": { + "workflow_user_id_idx": { + "name": "workflow_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_workspace_id_idx": { + "name": "workflow_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_user_workspace_idx": { + "name": "workflow_user_workspace_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_user_id_user_id_fk": { + "name": "workflow_user_id_user_id_fk", + "tableFrom": "workflow", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_workspace_id_workspace_id_fk": { + "name": "workflow_workspace_id_workspace_id_fk", + "tableFrom": "workflow", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_folder_id_workflow_folder_id_fk": { + "name": "workflow_folder_id_workflow_folder_id_fk", + "tableFrom": "workflow", + "tableTo": "workflow_folder", + "columnsFrom": [ + "folder_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_blocks": { + "name": "workflow_blocks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "position_x": { + "name": "position_x", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "position_y": { + "name": "position_y", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "horizontal_handles": { + "name": "horizontal_handles", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "is_wide": { + "name": "is_wide", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "advanced_mode": { + "name": "advanced_mode", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "trigger_mode": { + "name": "trigger_mode", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "height": { + "name": "height", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "sub_blocks": { + "name": "sub_blocks", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "outputs": { + "name": "outputs", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_blocks_workflow_id_idx": { + "name": "workflow_blocks_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_blocks_workflow_id_workflow_id_fk": { + "name": "workflow_blocks_workflow_id_workflow_id_fk", + "tableFrom": "workflow_blocks", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_checkpoints": { + "name": "workflow_checkpoints", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chat_id": { + "name": "chat_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "message_id": { + "name": "message_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workflow_state": { + "name": "workflow_state", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_checkpoints_user_id_idx": { + "name": "workflow_checkpoints_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_workflow_id_idx": { + "name": "workflow_checkpoints_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_chat_id_idx": { + "name": "workflow_checkpoints_chat_id_idx", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_message_id_idx": { + "name": "workflow_checkpoints_message_id_idx", + "columns": [ + { + "expression": "message_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_user_workflow_idx": { + "name": "workflow_checkpoints_user_workflow_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_workflow_chat_idx": { + "name": "workflow_checkpoints_workflow_chat_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_created_at_idx": { + "name": "workflow_checkpoints_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_chat_created_at_idx": { + "name": "workflow_checkpoints_chat_created_at_idx", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_checkpoints_user_id_user_id_fk": { + "name": "workflow_checkpoints_user_id_user_id_fk", + "tableFrom": "workflow_checkpoints", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_checkpoints_workflow_id_workflow_id_fk": { + "name": "workflow_checkpoints_workflow_id_workflow_id_fk", + "tableFrom": "workflow_checkpoints", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_checkpoints_chat_id_copilot_chats_id_fk": { + "name": "workflow_checkpoints_chat_id_copilot_chats_id_fk", + "tableFrom": "workflow_checkpoints", + "tableTo": "copilot_chats", + "columnsFrom": [ + "chat_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_deployment_version": { + "name": "workflow_deployment_version", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "state": { + "name": "state", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "workflow_deployment_version_workflow_version_unique": { + "name": "workflow_deployment_version_workflow_version_unique", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "version", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_deployment_version_workflow_active_idx": { + "name": "workflow_deployment_version_workflow_active_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "is_active", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_deployment_version_created_at_idx": { + "name": "workflow_deployment_version_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_deployment_version_workflow_id_workflow_id_fk": { + "name": "workflow_deployment_version_workflow_id_workflow_id_fk", + "tableFrom": "workflow_deployment_version", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_edges": { + "name": "workflow_edges", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_block_id": { + "name": "source_block_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "target_block_id": { + "name": "target_block_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_handle": { + "name": "source_handle", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "target_handle": { + "name": "target_handle", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_edges_workflow_id_idx": { + "name": "workflow_edges_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_edges_workflow_source_idx": { + "name": "workflow_edges_workflow_source_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "source_block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_edges_workflow_target_idx": { + "name": "workflow_edges_workflow_target_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "target_block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_edges_workflow_id_workflow_id_fk": { + "name": "workflow_edges_workflow_id_workflow_id_fk", + "tableFrom": "workflow_edges", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_edges_source_block_id_workflow_blocks_id_fk": { + "name": "workflow_edges_source_block_id_workflow_blocks_id_fk", + "tableFrom": "workflow_edges", + "tableTo": "workflow_blocks", + "columnsFrom": [ + "source_block_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_edges_target_block_id_workflow_blocks_id_fk": { + "name": "workflow_edges_target_block_id_workflow_blocks_id_fk", + "tableFrom": "workflow_edges", + "tableTo": "workflow_blocks", + "columnsFrom": [ + "target_block_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_execution_logs": { + "name": "workflow_execution_logs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_id": { + "name": "execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state_snapshot_id": { + "name": "state_snapshot_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "deployment_version_id": { + "name": "deployment_version_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "level": { + "name": "level", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "trigger": { + "name": "trigger", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "total_duration_ms": { + "name": "total_duration_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "execution_data": { + "name": "execution_data", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "cost": { + "name": "cost", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "files": { + "name": "files", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_execution_logs_workflow_id_idx": { + "name": "workflow_execution_logs_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_state_snapshot_id_idx": { + "name": "workflow_execution_logs_state_snapshot_id_idx", + "columns": [ + { + "expression": "state_snapshot_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_deployment_version_id_idx": { + "name": "workflow_execution_logs_deployment_version_id_idx", + "columns": [ + { + "expression": "deployment_version_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_trigger_idx": { + "name": "workflow_execution_logs_trigger_idx", + "columns": [ + { + "expression": "trigger", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_level_idx": { + "name": "workflow_execution_logs_level_idx", + "columns": [ + { + "expression": "level", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_started_at_idx": { + "name": "workflow_execution_logs_started_at_idx", + "columns": [ + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_execution_id_unique": { + "name": "workflow_execution_logs_execution_id_unique", + "columns": [ + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_workflow_started_at_idx": { + "name": "workflow_execution_logs_workflow_started_at_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_execution_logs_workflow_id_workflow_id_fk": { + "name": "workflow_execution_logs_workflow_id_workflow_id_fk", + "tableFrom": "workflow_execution_logs", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_execution_logs_state_snapshot_id_workflow_execution_snapshots_id_fk": { + "name": "workflow_execution_logs_state_snapshot_id_workflow_execution_snapshots_id_fk", + "tableFrom": "workflow_execution_logs", + "tableTo": "workflow_execution_snapshots", + "columnsFrom": [ + "state_snapshot_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "workflow_execution_logs_deployment_version_id_workflow_deployment_version_id_fk": { + "name": "workflow_execution_logs_deployment_version_id_workflow_deployment_version_id_fk", + "tableFrom": "workflow_execution_logs", + "tableTo": "workflow_deployment_version", + "columnsFrom": [ + "deployment_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_execution_snapshots": { + "name": "workflow_execution_snapshots", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state_hash": { + "name": "state_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state_data": { + "name": "state_data", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_snapshots_workflow_id_idx": { + "name": "workflow_snapshots_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_snapshots_hash_idx": { + "name": "workflow_snapshots_hash_idx", + "columns": [ + { + "expression": "state_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_snapshots_workflow_hash_idx": { + "name": "workflow_snapshots_workflow_hash_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "state_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_snapshots_created_at_idx": { + "name": "workflow_snapshots_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_execution_snapshots_workflow_id_workflow_id_fk": { + "name": "workflow_execution_snapshots_workflow_id_workflow_id_fk", + "tableFrom": "workflow_execution_snapshots", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_folder": { + "name": "workflow_folder", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parent_id": { + "name": "parent_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'#6B7280'" + }, + "is_expanded": { + "name": "is_expanded", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_folder_user_idx": { + "name": "workflow_folder_user_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_folder_workspace_parent_idx": { + "name": "workflow_folder_workspace_parent_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_folder_parent_sort_idx": { + "name": "workflow_folder_parent_sort_idx", + "columns": [ + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "sort_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_folder_user_id_user_id_fk": { + "name": "workflow_folder_user_id_user_id_fk", + "tableFrom": "workflow_folder", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_folder_workspace_id_workspace_id_fk": { + "name": "workflow_folder_workspace_id_workspace_id_fk", + "tableFrom": "workflow_folder", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_mcp_server": { + "name": "workflow_mcp_server", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_published": { + "name": "is_published", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "published_at": { + "name": "published_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_mcp_server_workspace_id_idx": { + "name": "workflow_mcp_server_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_mcp_server_created_by_idx": { + "name": "workflow_mcp_server_created_by_idx", + "columns": [ + { + "expression": "created_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_mcp_server_is_published_idx": { + "name": "workflow_mcp_server_is_published_idx", + "columns": [ + { + "expression": "is_published", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_mcp_server_workspace_id_workspace_id_fk": { + "name": "workflow_mcp_server_workspace_id_workspace_id_fk", + "tableFrom": "workflow_mcp_server", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_mcp_server_created_by_user_id_fk": { + "name": "workflow_mcp_server_created_by_user_id_fk", + "tableFrom": "workflow_mcp_server", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_mcp_tool": { + "name": "workflow_mcp_tool", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "server_id": { + "name": "server_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tool_name": { + "name": "tool_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tool_description": { + "name": "tool_description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "parameter_schema": { + "name": "parameter_schema", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "is_enabled": { + "name": "is_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_mcp_tool_server_id_idx": { + "name": "workflow_mcp_tool_server_id_idx", + "columns": [ + { + "expression": "server_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_mcp_tool_workflow_id_idx": { + "name": "workflow_mcp_tool_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_mcp_tool_server_workflow_unique": { + "name": "workflow_mcp_tool_server_workflow_unique", + "columns": [ + { + "expression": "server_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_mcp_tool_server_id_workflow_mcp_server_id_fk": { + "name": "workflow_mcp_tool_server_id_workflow_mcp_server_id_fk", + "tableFrom": "workflow_mcp_tool", + "tableTo": "workflow_mcp_server", + "columnsFrom": [ + "server_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_mcp_tool_workflow_id_workflow_id_fk": { + "name": "workflow_mcp_tool_workflow_id_workflow_id_fk", + "tableFrom": "workflow_mcp_tool", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_schedule": { + "name": "workflow_schedule", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "block_id": { + "name": "block_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cron_expression": { + "name": "cron_expression", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "next_run_at": { + "name": "next_run_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_ran_at": { + "name": "last_ran_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_queued_at": { + "name": "last_queued_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "trigger_type": { + "name": "trigger_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "timezone": { + "name": "timezone", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'UTC'" + }, + "failed_count": { + "name": "failed_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "last_failed_at": { + "name": "last_failed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_schedule_workflow_block_unique": { + "name": "workflow_schedule_workflow_block_unique", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_schedule_workflow_id_workflow_id_fk": { + "name": "workflow_schedule_workflow_id_workflow_id_fk", + "tableFrom": "workflow_schedule", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_schedule_block_id_workflow_blocks_id_fk": { + "name": "workflow_schedule_block_id_workflow_blocks_id_fk", + "tableFrom": "workflow_schedule", + "tableTo": "workflow_blocks", + "columnsFrom": [ + "block_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_subflows": { + "name": "workflow_subflows", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_subflows_workflow_id_idx": { + "name": "workflow_subflows_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_subflows_workflow_type_idx": { + "name": "workflow_subflows_workflow_type_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_subflows_workflow_id_workflow_id_fk": { + "name": "workflow_subflows_workflow_id_workflow_id_fk", + "tableFrom": "workflow_subflows", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace": { + "name": "workspace", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "owner_id": { + "name": "owner_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "billed_account_user_id": { + "name": "billed_account_user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "allow_personal_api_keys": { + "name": "allow_personal_api_keys", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workspace_owner_id_user_id_fk": { + "name": "workspace_owner_id_user_id_fk", + "tableFrom": "workspace", + "tableTo": "user", + "columnsFrom": [ + "owner_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_billed_account_user_id_user_id_fk": { + "name": "workspace_billed_account_user_id_user_id_fk", + "tableFrom": "workspace", + "tableTo": "user", + "columnsFrom": [ + "billed_account_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_environment": { + "name": "workspace_environment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "variables": { + "name": "variables", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_environment_workspace_unique": { + "name": "workspace_environment_workspace_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_environment_workspace_id_workspace_id_fk": { + "name": "workspace_environment_workspace_id_workspace_id_fk", + "tableFrom": "workspace_environment", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_file": { + "name": "workspace_file", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "uploaded_by": { + "name": "uploaded_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "uploaded_at": { + "name": "uploaded_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_file_workspace_id_idx": { + "name": "workspace_file_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_file_key_idx": { + "name": "workspace_file_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_file_workspace_id_workspace_id_fk": { + "name": "workspace_file_workspace_id_workspace_id_fk", + "tableFrom": "workspace_file", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_file_uploaded_by_user_id_fk": { + "name": "workspace_file_uploaded_by_user_id_fk", + "tableFrom": "workspace_file", + "tableTo": "user", + "columnsFrom": [ + "uploaded_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_file_key_unique": { + "name": "workspace_file_key_unique", + "nullsNotDistinct": false, + "columns": [ + "key" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_files": { + "name": "workspace_files", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "context": { + "name": "context", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "original_name": { + "name": "original_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content_type": { + "name": "content_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "uploaded_at": { + "name": "uploaded_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_files_key_idx": { + "name": "workspace_files_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_user_id_idx": { + "name": "workspace_files_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_workspace_id_idx": { + "name": "workspace_files_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_context_idx": { + "name": "workspace_files_context_idx", + "columns": [ + { + "expression": "context", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_files_user_id_user_id_fk": { + "name": "workspace_files_user_id_user_id_fk", + "tableFrom": "workspace_files", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_files_workspace_id_workspace_id_fk": { + "name": "workspace_files_workspace_id_workspace_id_fk", + "tableFrom": "workspace_files", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_files_key_unique": { + "name": "workspace_files_key_unique", + "nullsNotDistinct": false, + "columns": [ + "key" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_invitation": { + "name": "workspace_invitation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'member'" + }, + "status": { + "name": "status", + "type": "workspace_invitation_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "permissions": { + "name": "permissions", + "type": "permission_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'admin'" + }, + "org_invitation_id": { + "name": "org_invitation_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workspace_invitation_workspace_id_workspace_id_fk": { + "name": "workspace_invitation_workspace_id_workspace_id_fk", + "tableFrom": "workspace_invitation", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_invitation_inviter_id_user_id_fk": { + "name": "workspace_invitation_inviter_id_user_id_fk", + "tableFrom": "workspace_invitation", + "tableTo": "user", + "columnsFrom": [ + "inviter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_invitation_token_unique": { + "name": "workspace_invitation_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_notification_delivery": { + "name": "workspace_notification_delivery", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "subscription_id": { + "name": "subscription_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_id": { + "name": "execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "notification_delivery_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "attempts": { + "name": "attempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_attempt_at": { + "name": "last_attempt_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "next_attempt_at": { + "name": "next_attempt_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "response_status": { + "name": "response_status", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "response_body": { + "name": "response_body", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_notification_delivery_subscription_id_idx": { + "name": "workspace_notification_delivery_subscription_id_idx", + "columns": [ + { + "expression": "subscription_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_notification_delivery_execution_id_idx": { + "name": "workspace_notification_delivery_execution_id_idx", + "columns": [ + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_notification_delivery_status_idx": { + "name": "workspace_notification_delivery_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_notification_delivery_next_attempt_idx": { + "name": "workspace_notification_delivery_next_attempt_idx", + "columns": [ + { + "expression": "next_attempt_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_notification_delivery_subscription_id_workspace_notification_subscription_id_fk": { + "name": "workspace_notification_delivery_subscription_id_workspace_notification_subscription_id_fk", + "tableFrom": "workspace_notification_delivery", + "tableTo": "workspace_notification_subscription", + "columnsFrom": [ + "subscription_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_notification_delivery_workflow_id_workflow_id_fk": { + "name": "workspace_notification_delivery_workflow_id_workflow_id_fk", + "tableFrom": "workspace_notification_delivery", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_notification_subscription": { + "name": "workspace_notification_subscription", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "notification_type": { + "name": "notification_type", + "type": "notification_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "workflow_ids": { + "name": "workflow_ids", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'::text[]" + }, + "all_workflows": { + "name": "all_workflows", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "level_filter": { + "name": "level_filter", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY['info', 'error']::text[]" + }, + "trigger_filter": { + "name": "trigger_filter", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY['api', 'webhook', 'schedule', 'manual', 'chat']::text[]" + }, + "include_final_output": { + "name": "include_final_output", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "include_trace_spans": { + "name": "include_trace_spans", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "include_rate_limits": { + "name": "include_rate_limits", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "include_usage_data": { + "name": "include_usage_data", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "webhook_config": { + "name": "webhook_config", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "email_recipients": { + "name": "email_recipients", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "slack_config": { + "name": "slack_config", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "alert_config": { + "name": "alert_config", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "last_alert_at": { + "name": "last_alert_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_notification_workspace_id_idx": { + "name": "workspace_notification_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_notification_active_idx": { + "name": "workspace_notification_active_idx", + "columns": [ + { + "expression": "active", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_notification_type_idx": { + "name": "workspace_notification_type_idx", + "columns": [ + { + "expression": "notification_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_notification_subscription_workspace_id_workspace_id_fk": { + "name": "workspace_notification_subscription_workspace_id_workspace_id_fk", + "tableFrom": "workspace_notification_subscription", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_notification_subscription_created_by_user_id_fk": { + "name": "workspace_notification_subscription_created_by_user_id_fk", + "tableFrom": "workspace_notification_subscription", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.billing_blocked_reason": { + "name": "billing_blocked_reason", + "schema": "public", + "values": [ + "payment_failed", + "dispute" + ] + }, + "public.notification_delivery_status": { + "name": "notification_delivery_status", + "schema": "public", + "values": [ + "pending", + "in_progress", + "success", + "failed" + ] + }, + "public.notification_type": { + "name": "notification_type", + "schema": "public", + "values": [ + "webhook", + "email", + "slack" + ] + }, + "public.permission_type": { + "name": "permission_type", + "schema": "public", + "values": [ + "admin", + "write", + "read" + ] + }, + "public.template_creator_type": { + "name": "template_creator_type", + "schema": "public", + "values": [ + "user", + "organization" + ] + }, + "public.template_status": { + "name": "template_status", + "schema": "public", + "values": [ + "pending", + "approved", + "rejected" + ] + }, + "public.workspace_invitation_status": { + "name": "workspace_invitation_status", + "schema": "public", + "values": [ + "pending", + "accepted", + "rejected", + "cancelled" + ] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/packages/db/migrations/meta/_journal.json b/packages/db/migrations/meta/_journal.json index f793d74bf8..893da4753f 100644 --- a/packages/db/migrations/meta/_journal.json +++ b/packages/db/migrations/meta/_journal.json @@ -855,6 +855,20 @@ "when": 1765587157593, "tag": "0122_pale_absorbing_man", "breakpoints": true + }, + { + "idx": 123, + "version": "7", + "when": 1765932898404, + "tag": "0123_windy_lockheed", + "breakpoints": true + }, + { + "idx": 124, + "version": "7", + "when": 1766018207289, + "tag": "0124_amused_lyja", + "breakpoints": true } ] -} +} \ No newline at end of file From cfbe4a4790a44f2717726f0b6f1f8d660e99c0fd Mon Sep 17 00:00:00 2001 From: "priyanshu.solanki" Date: Wed, 17 Dec 2025 17:40:07 -0700 Subject: [PATCH 07/27] fix lint errors --- .../db/migrations/meta/0123_snapshot.json | 2 +- .../db/migrations/meta/0124_snapshot.json | 716 +++++------------- packages/db/migrations/meta/_journal.json | 2 +- 3 files changed, 178 insertions(+), 542 deletions(-) diff --git a/packages/db/migrations/meta/0123_snapshot.json b/packages/db/migrations/meta/0123_snapshot.json index 419a02d6f5..4001416fd3 100644 --- a/packages/db/migrations/meta/0123_snapshot.json +++ b/packages/db/migrations/meta/0123_snapshot.json @@ -7719,4 +7719,4 @@ "schemas": {}, "tables": {} } -} \ No newline at end of file +} diff --git a/packages/db/migrations/meta/0124_snapshot.json b/packages/db/migrations/meta/0124_snapshot.json index 46103bd0dd..13bdeaea76 100644 --- a/packages/db/migrations/meta/0124_snapshot.json +++ b/packages/db/migrations/meta/0124_snapshot.json @@ -157,12 +157,8 @@ "name": "account_user_id_user_id_fk", "tableFrom": "account", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -253,12 +249,8 @@ "name": "api_key_user_id_user_id_fk", "tableFrom": "api_key", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -266,12 +258,8 @@ "name": "api_key_workspace_id_workspace_id_fk", "tableFrom": "api_key", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -279,12 +267,8 @@ "name": "api_key_created_by_user_id_fk", "tableFrom": "api_key", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -294,9 +278,7 @@ "api_key_key_unique": { "name": "api_key_key_unique", "nullsNotDistinct": false, - "columns": [ - "key" - ] + "columns": ["key"] } }, "policies": {}, @@ -426,12 +408,8 @@ "name": "chat_workflow_id_workflow_id_fk", "tableFrom": "chat", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -439,12 +417,8 @@ "name": "chat_user_id_user_id_fk", "tableFrom": "chat", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -625,12 +599,8 @@ "name": "copilot_chats_user_id_user_id_fk", "tableFrom": "copilot_chats", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -638,12 +608,8 @@ "name": "copilot_chats_workflow_id_workflow_id_fk", "tableFrom": "copilot_chats", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -810,12 +776,8 @@ "name": "copilot_feedback_user_id_user_id_fk", "tableFrom": "copilot_feedback", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -823,12 +785,8 @@ "name": "copilot_feedback_chat_id_copilot_chats_id_fk", "tableFrom": "copilot_feedback", "tableTo": "copilot_chats", - "columnsFrom": [ - "chat_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["chat_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -937,12 +895,8 @@ "name": "custom_tools_workspace_id_workspace_id_fk", "tableFrom": "custom_tools", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -950,12 +904,8 @@ "name": "custom_tools_user_id_user_id_fk", "tableFrom": "custom_tools", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -1518,12 +1468,8 @@ "name": "document_knowledge_base_id_knowledge_base_id_fk", "tableFrom": "document", "tableTo": "knowledge_base", - "columnsFrom": [ - "knowledge_base_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -1945,12 +1891,8 @@ "name": "embedding_knowledge_base_id_knowledge_base_id_fk", "tableFrom": "embedding", "tableTo": "knowledge_base", - "columnsFrom": [ - "knowledge_base_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -1958,12 +1900,8 @@ "name": "embedding_document_id_document_id_fk", "tableFrom": "embedding", "tableTo": "document", - "columnsFrom": [ - "document_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["document_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2015,12 +1953,8 @@ "name": "environment_user_id_user_id_fk", "tableFrom": "environment", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2030,9 +1964,7 @@ "environment_user_id_unique": { "name": "environment_user_id_unique", "nullsNotDistinct": false, - "columns": [ - "user_id" - ] + "columns": ["user_id"] } }, "policies": {}, @@ -2221,12 +2153,8 @@ "name": "invitation_inviter_id_user_id_fk", "tableFrom": "invitation", "tableTo": "user", - "columnsFrom": [ - "inviter_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["inviter_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2234,12 +2162,8 @@ "name": "invitation_organization_id_organization_id_fk", "tableFrom": "invitation", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2406,12 +2330,8 @@ "name": "knowledge_base_user_id_user_id_fk", "tableFrom": "knowledge_base", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2419,12 +2339,8 @@ "name": "knowledge_base_workspace_id_workspace_id_fk", "tableFrom": "knowledge_base", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" } @@ -2549,12 +2465,8 @@ "name": "knowledge_base_tag_definitions_knowledge_base_id_knowledge_base_id_fk", "tableFrom": "knowledge_base_tag_definitions", "tableTo": "knowledge_base", - "columnsFrom": [ - "knowledge_base_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2761,12 +2673,8 @@ "name": "mcp_servers_workspace_id_workspace_id_fk", "tableFrom": "mcp_servers", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2774,12 +2682,8 @@ "name": "mcp_servers_created_by_user_id_fk", "tableFrom": "mcp_servers", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -2863,12 +2767,8 @@ "name": "member_user_id_user_id_fk", "tableFrom": "member", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2876,12 +2776,8 @@ "name": "member_organization_id_organization_id_fk", "tableFrom": "member", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2999,12 +2895,8 @@ "name": "memory_workflow_id_workflow_id_fk", "tableFrom": "memory", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3233,12 +3125,8 @@ "name": "paused_executions_workflow_id_workflow_id_fk", "tableFrom": "paused_executions", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3444,12 +3332,8 @@ "name": "permissions_user_id_user_id_fk", "tableFrom": "permissions", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3620,12 +3504,8 @@ "name": "resume_queue_paused_execution_id_paused_executions_id_fk", "tableFrom": "resume_queue", "tableTo": "paused_executions", - "columnsFrom": [ - "paused_execution_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["paused_execution_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3732,12 +3612,8 @@ "name": "session_user_id_user_id_fk", "tableFrom": "session", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -3745,12 +3621,8 @@ "name": "session_active_organization_id_organization_id_fk", "tableFrom": "session", "tableTo": "organization", - "columnsFrom": [ - "active_organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["active_organization_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -3760,9 +3632,7 @@ "session_token_unique": { "name": "session_token_unique", "nullsNotDistinct": false, - "columns": [ - "token" - ] + "columns": ["token"] } }, "policies": {}, @@ -3869,12 +3739,8 @@ "name": "settings_user_id_user_id_fk", "tableFrom": "settings", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3884,9 +3750,7 @@ "settings_user_id_unique": { "name": "settings_user_id_unique", "nullsNotDistinct": false, - "columns": [ - "user_id" - ] + "columns": ["user_id"] } }, "policies": {}, @@ -4013,12 +3877,8 @@ "name": "sso_provider_user_id_user_id_fk", "tableFrom": "sso_provider", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -4026,12 +3886,8 @@ "name": "sso_provider_organization_id_organization_id_fk", "tableFrom": "sso_provider", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4287,12 +4143,8 @@ "name": "template_creators_created_by_user_id_fk", "tableFrom": "template_creators", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -4476,12 +4328,8 @@ "name": "template_stars_user_id_user_id_fk", "tableFrom": "template_stars", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -4489,12 +4337,8 @@ "name": "template_stars_template_id_templates_id_fk", "tableFrom": "template_stars", "tableTo": "templates", - "columnsFrom": [ - "template_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["template_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4735,12 +4579,8 @@ "name": "templates_workflow_id_workflow_id_fk", "tableFrom": "templates", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -4748,12 +4588,8 @@ "name": "templates_creator_id_template_creators_id_fk", "tableFrom": "templates", "tableTo": "template_creators", - "columnsFrom": [ - "creator_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["creator_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -4831,9 +4667,7 @@ "user_email_unique": { "name": "user_email_unique", "nullsNotDistinct": false, - "columns": [ - "email" - ] + "columns": ["email"] } }, "policies": {}, @@ -5024,12 +4858,8 @@ "name": "user_stats_user_id_user_id_fk", "tableFrom": "user_stats", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -5039,9 +4869,7 @@ "user_stats_user_id_unique": { "name": "user_stats_user_id_unique", "nullsNotDistinct": false, - "columns": [ - "user_id" - ] + "columns": ["user_id"] } }, "policies": {}, @@ -5158,9 +4986,7 @@ "waitlist_email_unique": { "name": "waitlist_email_unique", "nullsNotDistinct": false, - "columns": [ - "email" - ] + "columns": ["email"] } }, "policies": {}, @@ -5285,12 +5111,8 @@ "name": "webhook_workflow_id_workflow_id_fk", "tableFrom": "webhook", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5298,12 +5120,8 @@ "name": "webhook_block_id_workflow_blocks_id_fk", "tableFrom": "webhook", "tableTo": "workflow_blocks", - "columnsFrom": [ - "block_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["block_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -5471,12 +5289,8 @@ "name": "workflow_user_id_user_id_fk", "tableFrom": "workflow", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5484,12 +5298,8 @@ "name": "workflow_workspace_id_workspace_id_fk", "tableFrom": "workflow", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5497,12 +5307,8 @@ "name": "workflow_folder_id_workflow_folder_id_fk", "tableFrom": "workflow", "tableTo": "workflow_folder", - "columnsFrom": [ - "folder_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["folder_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -5653,12 +5459,8 @@ "name": "workflow_blocks_workflow_id_workflow_id_fk", "tableFrom": "workflow_blocks", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -5870,12 +5672,8 @@ "name": "workflow_checkpoints_user_id_user_id_fk", "tableFrom": "workflow_checkpoints", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5883,12 +5681,8 @@ "name": "workflow_checkpoints_workflow_id_workflow_id_fk", "tableFrom": "workflow_checkpoints", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5896,12 +5690,8 @@ "name": "workflow_checkpoints_chat_id_copilot_chats_id_fk", "tableFrom": "workflow_checkpoints", "tableTo": "copilot_chats", - "columnsFrom": [ - "chat_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["chat_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -6031,12 +5821,8 @@ "name": "workflow_deployment_version_workflow_id_workflow_id_fk", "tableFrom": "workflow_deployment_version", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -6159,12 +5945,8 @@ "name": "workflow_edges_workflow_id_workflow_id_fk", "tableFrom": "workflow_edges", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -6172,12 +5954,8 @@ "name": "workflow_edges_source_block_id_workflow_blocks_id_fk", "tableFrom": "workflow_edges", "tableTo": "workflow_blocks", - "columnsFrom": [ - "source_block_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["source_block_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -6185,12 +5963,8 @@ "name": "workflow_edges_target_block_id_workflow_blocks_id_fk", "tableFrom": "workflow_edges", "tableTo": "workflow_blocks", - "columnsFrom": [ - "target_block_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["target_block_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -6425,12 +6199,8 @@ "name": "workflow_execution_logs_workflow_id_workflow_id_fk", "tableFrom": "workflow_execution_logs", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -6438,12 +6208,8 @@ "name": "workflow_execution_logs_state_snapshot_id_workflow_execution_snapshots_id_fk", "tableFrom": "workflow_execution_logs", "tableTo": "workflow_execution_snapshots", - "columnsFrom": [ - "state_snapshot_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["state_snapshot_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" }, @@ -6451,12 +6217,8 @@ "name": "workflow_execution_logs_deployment_version_id_workflow_deployment_version_id_fk", "tableFrom": "workflow_execution_logs", "tableTo": "workflow_deployment_version", - "columnsFrom": [ - "deployment_version_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["deployment_version_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -6576,12 +6338,8 @@ "name": "workflow_execution_snapshots_workflow_id_workflow_id_fk", "tableFrom": "workflow_execution_snapshots", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -6726,12 +6484,8 @@ "name": "workflow_folder_user_id_user_id_fk", "tableFrom": "workflow_folder", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -6739,12 +6493,8 @@ "name": "workflow_folder_workspace_id_workspace_id_fk", "tableFrom": "workflow_folder", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -6869,12 +6619,8 @@ "name": "workflow_mcp_server_workspace_id_workspace_id_fk", "tableFrom": "workflow_mcp_server", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -6882,12 +6628,8 @@ "name": "workflow_mcp_server_created_by_user_id_fk", "tableFrom": "workflow_mcp_server", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -7019,12 +6761,8 @@ "name": "workflow_mcp_tool_server_id_workflow_mcp_server_id_fk", "tableFrom": "workflow_mcp_tool", "tableTo": "workflow_mcp_server", - "columnsFrom": [ - "server_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["server_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -7032,12 +6770,8 @@ "name": "workflow_mcp_tool_workflow_id_workflow_id_fk", "tableFrom": "workflow_mcp_tool", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -7170,12 +6904,8 @@ "name": "workflow_schedule_workflow_id_workflow_id_fk", "tableFrom": "workflow_schedule", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -7183,12 +6913,8 @@ "name": "workflow_schedule_block_id_workflow_blocks_id_fk", "tableFrom": "workflow_schedule", "tableTo": "workflow_blocks", - "columnsFrom": [ - "block_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["block_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -7286,12 +7012,8 @@ "name": "workflow_subflows_workflow_id_workflow_id_fk", "tableFrom": "workflow_subflows", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -7358,12 +7080,8 @@ "name": "workspace_owner_id_user_id_fk", "tableFrom": "workspace", "tableTo": "user", - "columnsFrom": [ - "owner_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["owner_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -7371,12 +7089,8 @@ "name": "workspace_billed_account_user_id_user_id_fk", "tableFrom": "workspace", "tableTo": "user", - "columnsFrom": [ - "billed_account_user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["billed_account_user_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" } @@ -7447,12 +7161,8 @@ "name": "workspace_environment_workspace_id_workspace_id_fk", "tableFrom": "workspace_environment", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -7554,12 +7264,8 @@ "name": "workspace_file_workspace_id_workspace_id_fk", "tableFrom": "workspace_file", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -7567,12 +7273,8 @@ "name": "workspace_file_uploaded_by_user_id_fk", "tableFrom": "workspace_file", "tableTo": "user", - "columnsFrom": [ - "uploaded_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["uploaded_by"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -7582,9 +7284,7 @@ "workspace_file_key_unique": { "name": "workspace_file_key_unique", "nullsNotDistinct": false, - "columns": [ - "key" - ] + "columns": ["key"] } }, "policies": {}, @@ -7718,12 +7418,8 @@ "name": "workspace_files_user_id_user_id_fk", "tableFrom": "workspace_files", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -7731,12 +7427,8 @@ "name": "workspace_files_workspace_id_workspace_id_fk", "tableFrom": "workspace_files", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -7746,9 +7438,7 @@ "workspace_files_key_unique": { "name": "workspace_files_key_unique", "nullsNotDistinct": false, - "columns": [ - "key" - ] + "columns": ["key"] } }, "policies": {}, @@ -7845,12 +7535,8 @@ "name": "workspace_invitation_workspace_id_workspace_id_fk", "tableFrom": "workspace_invitation", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -7858,12 +7544,8 @@ "name": "workspace_invitation_inviter_id_user_id_fk", "tableFrom": "workspace_invitation", "tableTo": "user", - "columnsFrom": [ - "inviter_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["inviter_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -7873,9 +7555,7 @@ "workspace_invitation_token_unique": { "name": "workspace_invitation_token_unique", "nullsNotDistinct": false, - "columns": [ - "token" - ] + "columns": ["token"] } }, "policies": {}, @@ -8037,12 +7717,8 @@ "name": "workspace_notification_delivery_subscription_id_workspace_notification_subscription_id_fk", "tableFrom": "workspace_notification_delivery", "tableTo": "workspace_notification_subscription", - "columnsFrom": [ - "subscription_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["subscription_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -8050,12 +7726,8 @@ "name": "workspace_notification_delivery_workflow_id_workflow_id_fk", "tableFrom": "workspace_notification_delivery", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -8255,12 +7927,8 @@ "name": "workspace_notification_subscription_workspace_id_workspace_id_fk", "tableFrom": "workspace_notification_subscription", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -8268,12 +7936,8 @@ "name": "workspace_notification_subscription_created_by_user_id_fk", "tableFrom": "workspace_notification_subscription", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -8289,65 +7953,37 @@ "public.billing_blocked_reason": { "name": "billing_blocked_reason", "schema": "public", - "values": [ - "payment_failed", - "dispute" - ] + "values": ["payment_failed", "dispute"] }, "public.notification_delivery_status": { "name": "notification_delivery_status", "schema": "public", - "values": [ - "pending", - "in_progress", - "success", - "failed" - ] + "values": ["pending", "in_progress", "success", "failed"] }, "public.notification_type": { "name": "notification_type", "schema": "public", - "values": [ - "webhook", - "email", - "slack" - ] + "values": ["webhook", "email", "slack"] }, "public.permission_type": { "name": "permission_type", "schema": "public", - "values": [ - "admin", - "write", - "read" - ] + "values": ["admin", "write", "read"] }, "public.template_creator_type": { "name": "template_creator_type", "schema": "public", - "values": [ - "user", - "organization" - ] + "values": ["user", "organization"] }, "public.template_status": { "name": "template_status", "schema": "public", - "values": [ - "pending", - "approved", - "rejected" - ] + "values": ["pending", "approved", "rejected"] }, "public.workspace_invitation_status": { "name": "workspace_invitation_status", "schema": "public", - "values": [ - "pending", - "accepted", - "rejected", - "cancelled" - ] + "values": ["pending", "accepted", "rejected", "cancelled"] } }, "schemas": {}, @@ -8360,4 +7996,4 @@ "schemas": {}, "tables": {} } -} \ No newline at end of file +} diff --git a/packages/db/migrations/meta/_journal.json b/packages/db/migrations/meta/_journal.json index 893da4753f..54eadd5e5d 100644 --- a/packages/db/migrations/meta/_journal.json +++ b/packages/db/migrations/meta/_journal.json @@ -871,4 +871,4 @@ "breakpoints": true } ] -} \ No newline at end of file +} From f2450d3c26cd1f221aef950831152582f4511e5e Mon Sep 17 00:00:00 2001 From: "priyanshu.solanki" Date: Wed, 17 Dec 2025 18:03:01 -0700 Subject: [PATCH 08/27] refactored code to use hasstartblock from the tirgger utils --- .../mcp/workflow-servers/[id]/tools/route.ts | 32 +----------- .../app/api/workflows/[id]/deploy/route.ts | 43 ++-------------- .../deployments/[version]/activate/route.ts | 37 ++------------ .../deployments/[version]/revert/route.ts | 37 ++------------ .../lib/workflows/triggers/trigger-utils.ts | 51 +++++++++++++++++++ 5 files changed, 67 insertions(+), 133 deletions(-) diff --git a/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts b/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts index 2a668a99c2..858797db64 100644 --- a/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts +++ b/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts @@ -6,7 +6,7 @@ import { createLogger } from '@/lib/logs/console/logger' import { getParsedBody, withMcpAuth } from '@/lib/mcp/middleware' import { createMcpErrorResponse, createMcpSuccessResponse } from '@/lib/mcp/utils' import { sanitizeToolName } from '@/lib/mcp/workflow-tool-schema' -import { loadWorkflowFromNormalizedTables } from '@/lib/workflows/persistence/utils' +import { hasValidStartBlock } from '@/lib/workflows/triggers/trigger-utils' const logger = createLogger('WorkflowMcpToolsAPI') @@ -16,36 +16,6 @@ interface RouteParams { id: string } -/** - * Check if a workflow has a valid start block that can accept inputs - */ -async function hasValidStartBlock(workflowId: string): Promise { - try { - const normalizedData = await loadWorkflowFromNormalizedTables(workflowId) - if (!normalizedData?.blocks) { - return false - } - - // Look for a start block - const startBlock = Object.values(normalizedData.blocks).find((block: any) => { - const blockType = block?.type - return ( - blockType === 'starter' || - blockType === 'start' || - blockType === 'start_trigger' || - blockType === 'api' || - blockType === 'api_trigger' || - blockType === 'input_trigger' - ) - }) - - return !!startBlock - } catch (error) { - logger.warn('Error checking for start block:', error) - return false - } -} - /** * GET - List all tools for a workflow MCP server */ diff --git a/apps/sim/app/api/workflows/[id]/deploy/route.ts b/apps/sim/app/api/workflows/[id]/deploy/route.ts index be390f5904..b17b240635 100644 --- a/apps/sim/app/api/workflows/[id]/deploy/route.ts +++ b/apps/sim/app/api/workflows/[id]/deploy/route.ts @@ -5,6 +5,10 @@ import { generateRequestId } from '@/lib/core/utils/request' import { createLogger } from '@/lib/logs/console/logger' import { deployWorkflow, loadWorkflowFromNormalizedTables } from '@/lib/workflows/persistence/utils' import { validateWorkflowPermissions } from '@/lib/workflows/utils' +import { + hasValidStartBlock, + isValidStartBlockType, +} from '@/lib/workflows/triggers/trigger-utils' import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils' const logger = createLogger('WorkflowDeployAPI') @@ -24,15 +28,7 @@ async function generateMcpToolSchema(workflowId: string): Promise { - const blockType = block?.type - return ( - blockType === 'starter' || - blockType === 'start' || - blockType === 'start_trigger' || - blockType === 'api' || - blockType === 'api_trigger' || - blockType === 'input_trigger' - ) + return isValidStartBlockType(block?.type) }) as any if (!startBlock?.subBlocks?.inputFormat?.value) { @@ -88,35 +84,6 @@ async function generateMcpToolSchema(workflowId: string): Promise { - try { - const normalizedData = await loadWorkflowFromNormalizedTables(workflowId) - if (!normalizedData?.blocks) { - return false - } - - const startBlock = Object.values(normalizedData.blocks).find((block: any) => { - const blockType = block?.type - return ( - blockType === 'starter' || - blockType === 'start' || - blockType === 'start_trigger' || - blockType === 'api' || - blockType === 'api_trigger' || - blockType === 'input_trigger' - ) - }) - - return !!startBlock - } catch (error) { - logger.warn('Error checking for start block:', error) - return false - } -} - /** * Update all MCP tools that reference this workflow with the latest parameter schema. * If the workflow no longer has a start block, remove all MCP tools. diff --git a/apps/sim/app/api/workflows/[id]/deployments/[version]/activate/route.ts b/apps/sim/app/api/workflows/[id]/deployments/[version]/activate/route.ts index ea8324e5a0..18b48c8c26 100644 --- a/apps/sim/app/api/workflows/[id]/deployments/[version]/activate/route.ts +++ b/apps/sim/app/api/workflows/[id]/deployments/[version]/activate/route.ts @@ -4,6 +4,10 @@ import type { NextRequest } from 'next/server' import { generateRequestId } from '@/lib/core/utils/request' import { createLogger } from '@/lib/logs/console/logger' import { validateWorkflowPermissions } from '@/lib/workflows/utils' +import { + hasValidStartBlockInState, + isValidStartBlockType, +} from '@/lib/workflows/triggers/trigger-utils' import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils' const logger = createLogger('WorkflowActivateDeploymentAPI') @@ -22,15 +26,7 @@ function generateMcpToolSchemaFromState(state: any): Record { // Find the start block in the deployed state const startBlock = Object.values(state.blocks).find((block: any) => { - const blockType = block?.type - return ( - blockType === 'starter' || - blockType === 'start' || - blockType === 'start_trigger' || - blockType === 'api' || - blockType === 'api_trigger' || - blockType === 'input_trigger' - ) + return isValidStartBlockType(block?.type) }) as any if (!startBlock?.subBlocks?.inputFormat?.value) { @@ -86,29 +82,6 @@ function generateMcpToolSchemaFromState(state: any): Record { } } -/** - * Check if a version state has a valid start block - */ -function hasValidStartBlockInState(state: any): boolean { - if (!state?.blocks) { - return false - } - - const startBlock = Object.values(state.blocks).find((block: any) => { - const blockType = block?.type - return ( - blockType === 'starter' || - blockType === 'start' || - blockType === 'start_trigger' || - blockType === 'api' || - blockType === 'api_trigger' || - blockType === 'input_trigger' - ) - }) - - return !!startBlock -} - /** * Sync MCP tools when activating a deployment version. * If the version has no start block, remove all MCP tools. diff --git a/apps/sim/app/api/workflows/[id]/deployments/[version]/revert/route.ts b/apps/sim/app/api/workflows/[id]/deployments/[version]/revert/route.ts index f645a23450..74e543a419 100644 --- a/apps/sim/app/api/workflows/[id]/deployments/[version]/revert/route.ts +++ b/apps/sim/app/api/workflows/[id]/deployments/[version]/revert/route.ts @@ -6,6 +6,10 @@ import { generateRequestId } from '@/lib/core/utils/request' import { createLogger } from '@/lib/logs/console/logger' import { saveWorkflowToNormalizedTables } from '@/lib/workflows/persistence/utils' import { validateWorkflowPermissions } from '@/lib/workflows/utils' +import { + hasValidStartBlockInState, + isValidStartBlockType, +} from '@/lib/workflows/triggers/trigger-utils' import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils' const logger = createLogger('RevertToDeploymentVersionAPI') @@ -24,15 +28,7 @@ function generateMcpToolSchemaFromState(state: any): Record { // Find the start block in the deployed state const startBlock = Object.values(state.blocks).find((block: any) => { - const blockType = block?.type - return ( - blockType === 'starter' || - blockType === 'start' || - blockType === 'start_trigger' || - blockType === 'api' || - blockType === 'api_trigger' || - blockType === 'input_trigger' - ) + return isValidStartBlockType(block?.type) }) as any if (!startBlock?.subBlocks?.inputFormat?.value) { @@ -88,29 +84,6 @@ function generateMcpToolSchemaFromState(state: any): Record { } } -/** - * Check if a version state has a valid start block - */ -function hasValidStartBlockInState(state: any): boolean { - if (!state?.blocks) { - return false - } - - const startBlock = Object.values(state.blocks).find((block: any) => { - const blockType = block?.type - return ( - blockType === 'starter' || - blockType === 'start' || - blockType === 'start_trigger' || - blockType === 'api' || - blockType === 'api_trigger' || - blockType === 'input_trigger' - ) - }) - - return !!startBlock -} - /** * Sync MCP tools when reverting to a deployment version. * If the version has no start block, remove all MCP tools. diff --git a/apps/sim/lib/workflows/triggers/trigger-utils.ts b/apps/sim/lib/workflows/triggers/trigger-utils.ts index aaf6dbb697..56af72990b 100644 --- a/apps/sim/lib/workflows/triggers/trigger-utils.ts +++ b/apps/sim/lib/workflows/triggers/trigger-utils.ts @@ -7,9 +7,60 @@ import { import { getAllBlocks, getBlock } from '@/blocks' import type { BlockConfig } from '@/blocks/types' import { getTrigger } from '@/triggers' +import { loadWorkflowFromNormalizedTables } from '@/lib/workflows/persistence/utils' const logger = createLogger('TriggerUtils') +/** + * Valid start block types that can trigger a workflow + */ +export const VALID_START_BLOCK_TYPES = [ + 'starter', + 'start', + 'start_trigger', + 'api', + 'api_trigger', + 'input_trigger', +] as const + +export type ValidStartBlockType = (typeof VALID_START_BLOCK_TYPES)[number] + +/** + * Check if a block type is a valid start block type + */ +export function isValidStartBlockType(blockType: string): blockType is ValidStartBlockType { + return VALID_START_BLOCK_TYPES.includes(blockType as ValidStartBlockType) +} + +/** + * Check if a workflow state has a valid start block + */ +export function hasValidStartBlockInState(state: any): boolean { + if (!state?.blocks) { + return false + } + + const startBlock = Object.values(state.blocks).find((block: any) => { + const blockType = block?.type + return isValidStartBlockType(blockType) + }) + + return !!startBlock +} + +/** + * Check if a workflow has a valid start block by loading from database + */ +export async function hasValidStartBlock(workflowId: string): Promise { + try { + const normalizedData = await loadWorkflowFromNormalizedTables(workflowId) + return hasValidStartBlockInState(normalizedData) + } catch (error) { + logger.warn('Error checking for start block:', error) + return false + } +} + /** * Generates mock data based on the output type definition */ From 896e9674c26ab7f2fbf884b0e3c553d9e774ed74 Mon Sep 17 00:00:00 2001 From: "priyanshu.solanki" Date: Wed, 17 Dec 2025 18:58:51 -0700 Subject: [PATCH 09/27] removing unecessary auth --- apps/sim/lib/mcp/serve-auth.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/apps/sim/lib/mcp/serve-auth.ts b/apps/sim/lib/mcp/serve-auth.ts index 791ad97a6b..4edbbf2d3d 100644 --- a/apps/sim/lib/mcp/serve-auth.ts +++ b/apps/sim/lib/mcp/serve-auth.ts @@ -55,18 +55,6 @@ export async function validateMcpServeAuth( return { success: false, error: auth.error || 'Authentication required' } } - // Verify user has access to the workspace - const permissions = await getUserEntityPermissions(auth.userId, 'workspace', server.workspaceId) - - if (!permissions) { - // For published servers, we allow access to any authenticated user - // This enables the "public but authenticated" model where anyone with a Sim account - // can use published MCP servers - logger.info( - `User ${auth.userId} accessing published MCP server ${serverId} without workspace membership` - ) - } - return { success: true, userId: auth.userId, From 6c10f31a405dde750836b8faa4198b8f2a9d8614 Mon Sep 17 00:00:00 2001 From: "priyanshu.solanki" Date: Wed, 17 Dec 2025 21:20:30 -0700 Subject: [PATCH 10/27] using official mcp sdk and added description fields --- .../app/api/mcp/serve/[serverId]/sse/route.ts | 368 ++++------------ .../mcp/workflow-servers/[id]/tools/route.ts | 16 +- .../app/api/workflows/[id]/deploy/route.ts | 74 +--- .../deployments/[version]/activate/route.ts | 61 +-- .../deployments/[version]/revert/route.ts | 61 +-- .../components/mcp-tool/mcp-tool.tsx | 78 +++- apps/sim/lib/mcp/serve-auth.ts | 1 - apps/sim/lib/mcp/workflow-mcp-server.ts | 399 ++++++++++++++++++ apps/sim/lib/mcp/workflow-tool-schema.ts | 94 ++++- .../lib/workflows/triggers/trigger-utils.ts | 14 - apps/sim/lib/workflows/types.ts | 1 + apps/sim/package.json | 2 +- 12 files changed, 681 insertions(+), 488 deletions(-) create mode 100644 apps/sim/lib/mcp/workflow-mcp-server.ts diff --git a/apps/sim/app/api/mcp/serve/[serverId]/sse/route.ts b/apps/sim/app/api/mcp/serve/[serverId]/sse/route.ts index bf20ac2e94..7a926d2a51 100644 --- a/apps/sim/app/api/mcp/serve/[serverId]/sse/route.ts +++ b/apps/sim/app/api/mcp/serve/[serverId]/sse/route.ts @@ -1,11 +1,18 @@ +/** + * MCP SSE/HTTP Endpoint + * + * Implements MCP protocol using the official @modelcontextprotocol/sdk + * with a Next.js-compatible transport adapter. + */ + import { db } from '@sim/db' -import { workflow, workflowMcpServer, workflowMcpTool } from '@sim/db/schema' +import { workflowMcpServer } from '@sim/db/schema' import { eq } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { checkHybridAuth } from '@/lib/auth/hybrid' import { SSE_HEADERS } from '@/lib/core/utils/sse' -import { getBaseUrl } from '@/lib/core/utils/urls' import { createLogger } from '@/lib/logs/console/logger' +import { createMcpSseStream, handleMcpRequest } from '@/lib/mcp/workflow-mcp-server' const logger = createLogger('WorkflowMcpSSE') @@ -16,22 +23,6 @@ interface RouteParams { serverId: string } -/** - * MCP JSON-RPC Request/Response types - */ -interface JsonRpcMessage { - jsonrpc: '2.0' - id?: string | number - method?: string - params?: Record - result?: unknown - error?: { - code: number - message: string - data?: unknown - } -} - /** * Validate that the server exists and is published */ @@ -52,7 +43,7 @@ async function validateServer(serverId: string) { /** * GET - SSE endpoint for MCP protocol - * This establishes a Server-Sent Events connection for bidirectional MCP communication + * Establishes a Server-Sent Events connection for MCP notifications */ export async function GET(request: NextRequest, { params }: { params: Promise }) { const { serverId } = await params @@ -75,69 +66,17 @@ export async function GET(request: NextRequest, { params }: { params: Promise { - if (isStreamClosed) return - try { - const message = `event: ${event}\ndata: ${JSON.stringify(data)}\n\n` - controller.enqueue(encoder.encode(message)) - } catch { - isStreamClosed = true - } - } - - // Send initial connection event - sendEvent('open', { type: 'connection', status: 'connected' }) - - // Send server capabilities - sendEvent('message', { - jsonrpc: '2.0', - method: 'notifications/initialized', - params: { - protocolVersion: '2024-11-05', - capabilities: { - tools: {}, - }, - serverInfo: { - name: server.name, - version: '1.0.0', - }, - }, - }) - - // Keep connection alive with periodic pings - const pingInterval = setInterval(() => { - if (isStreamClosed) { - clearInterval(pingInterval) - return - } - sendEvent('ping', { timestamp: Date.now() }) - }, 30000) - - // Handle cleanup - request.signal.addEventListener('abort', () => { - isStreamClosed = true - clearInterval(pingInterval) - try { - controller.close() - } catch { - // Stream already closed - } - }) - }, - - cancel() { - isStreamClosed = true - logger.info(`SSE connection closed for server ${serverId}`) - }, + const apiKey = + request.headers.get('X-API-Key') || + request.headers.get('Authorization')?.replace('Bearer ', '') + + // Create SSE stream using the SDK-based server + const stream = createMcpSseStream({ + serverId, + serverName: server.name, + userId: auth.userId, + workspaceId: server.workspaceId, + apiKey, }) return new NextResponse(stream, { @@ -154,8 +93,8 @@ export async function GET(request: NextRequest, { params }: { params: Promise }) { const { serverId } = await params @@ -165,85 +104,61 @@ export async function POST(request: NextRequest, { params }: { params: Promise { - const tools = await db - .select({ - toolName: workflowMcpTool.toolName, - toolDescription: workflowMcpTool.toolDescription, - parameterSchema: workflowMcpTool.parameterSchema, - isEnabled: workflowMcpTool.isEnabled, - }) - .from(workflowMcpTool) - .where(eq(workflowMcpTool.serverId, serverId)) - - const mcpTools = tools - .filter((tool) => tool.isEnabled) - .map((tool) => ({ - name: tool.toolName, - description: tool.toolDescription || `Execute workflow tool: ${tool.toolName}`, - inputSchema: tool.parameterSchema || { - type: 'object', - properties: { - input: { - type: 'object', - description: 'Input data for the workflow', - }, - }, - }, - })) - - return NextResponse.json({ - jsonrpc: '2.0', - id, - result: { tools: mcpTools }, - }) -} - -/** - * Handle tools/call method + * DELETE - Handle session termination + * MCP clients may send DELETE to end a session */ -async function handleToolsCall( - message: JsonRpcMessage, - serverId: string, - userId: string, - workspaceId: string, - apiKey?: string | null -): Promise { - const params = message.params as { name: string; arguments?: Record } | undefined - - if (!params?.name) { - return NextResponse.json({ - jsonrpc: '2.0', - id: message.id || 0, - error: { code: -32602, message: 'Invalid params: tool name required' }, - }) - } - - // Find the tool - const tools = await db - .select({ - toolName: workflowMcpTool.toolName, - workflowId: workflowMcpTool.workflowId, - isEnabled: workflowMcpTool.isEnabled, - }) - .from(workflowMcpTool) - .where(eq(workflowMcpTool.serverId, serverId)) - - const tool = tools.find((t) => t.toolName === params.name) - - if (!tool) { - return NextResponse.json({ - jsonrpc: '2.0', - id: message.id || 0, - error: { code: -32602, message: `Tool not found: ${params.name}` }, - }) - } - - if (!tool.isEnabled) { - return NextResponse.json({ - jsonrpc: '2.0', - id: message.id || 0, - error: { code: -32602, message: `Tool is disabled: ${params.name}` }, - }) - } - - // Verify workflow is deployed - const [workflowRecord] = await db - .select({ id: workflow.id, isDeployed: workflow.isDeployed }) - .from(workflow) - .where(eq(workflow.id, tool.workflowId)) - .limit(1) - - if (!workflowRecord || !workflowRecord.isDeployed) { - return NextResponse.json({ - jsonrpc: '2.0', - id: message.id || 0, - error: { code: -32603, message: 'Workflow is not deployed' }, - }) - } - - // Execute the workflow - const baseUrl = getBaseUrl() - const executeUrl = `${baseUrl}/api/workflows/${tool.workflowId}/execute` - - logger.info(`Executing workflow ${tool.workflowId} via MCP SSE tool ${params.name}`) +export async function DELETE(request: NextRequest, { params }: { params: Promise }) { + const { serverId } = await params try { - // Build headers for the internal execute call - const executeHeaders: Record = { - 'Content-Type': 'application/json', - } + // Validate server exists + const server = await validateServer(serverId) - // Forward the API key for authentication - if (apiKey) { - executeHeaders['X-API-Key'] = apiKey + if (!server) { + return NextResponse.json({ error: 'Server not found' }, { status: 404 }) } - const executeResponse = await fetch(executeUrl, { - method: 'POST', - headers: executeHeaders, - body: JSON.stringify({ - input: params.arguments || {}, - triggerType: 'mcp', - }), - }) - - const executeResult = await executeResponse.json() - - if (!executeResponse.ok) { - return NextResponse.json({ - jsonrpc: '2.0', - id: message.id || 0, - error: { - code: -32603, - message: executeResult.error || 'Workflow execution failed', - }, - }) + // Check authentication + const auth = await checkHybridAuth(request, { requireWorkflowId: false }) + if (!auth.success || !auth.userId) { + return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } - // Format response for MCP - return NextResponse.json({ - jsonrpc: '2.0', - id: message.id, - result: { - content: [ - { - type: 'text', - text: JSON.stringify(executeResult.output || executeResult, null, 2), - }, - ], - isError: !executeResult.success, - }, - }) + logger.info(`MCP session terminated for server ${serverId}`) + + return new NextResponse(null, { status: 204 }) } catch (error) { - logger.error('Error executing workflow:', error) - return NextResponse.json({ - jsonrpc: '2.0', - id: message.id || 0, - error: { code: -32603, message: 'Tool execution failed' }, - }) + logger.error('Error handling MCP DELETE request:', error) + return NextResponse.json({ error: 'Internal server error' }, { status: 500 }) } } diff --git a/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts b/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts index 858797db64..ca875e8a15 100644 --- a/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts +++ b/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts @@ -6,10 +6,24 @@ import { createLogger } from '@/lib/logs/console/logger' import { getParsedBody, withMcpAuth } from '@/lib/mcp/middleware' import { createMcpErrorResponse, createMcpSuccessResponse } from '@/lib/mcp/utils' import { sanitizeToolName } from '@/lib/mcp/workflow-tool-schema' -import { hasValidStartBlock } from '@/lib/workflows/triggers/trigger-utils' +import { loadWorkflowFromNormalizedTables } from '@/lib/workflows/persistence/utils' +import { hasValidStartBlockInState } from '@/lib/workflows/triggers/trigger-utils' const logger = createLogger('WorkflowMcpToolsAPI') +/** + * Check if a workflow has a valid start block by loading from database + */ +async function hasValidStartBlock(workflowId: string): Promise { + try { + const normalizedData = await loadWorkflowFromNormalizedTables(workflowId) + return hasValidStartBlockInState(normalizedData) + } catch (error) { + logger.warn('Error checking for start block:', error) + return false + } +} + export const dynamic = 'force-dynamic' interface RouteParams { diff --git a/apps/sim/app/api/workflows/[id]/deploy/route.ts b/apps/sim/app/api/workflows/[id]/deploy/route.ts index b17b240635..c5232ce67c 100644 --- a/apps/sim/app/api/workflows/[id]/deploy/route.ts +++ b/apps/sim/app/api/workflows/[id]/deploy/route.ts @@ -3,16 +3,30 @@ import { and, desc, eq } from 'drizzle-orm' import type { NextRequest } from 'next/server' import { generateRequestId } from '@/lib/core/utils/request' import { createLogger } from '@/lib/logs/console/logger' +import { + extractInputFormatFromBlocks, + generateToolInputSchema, +} from '@/lib/mcp/workflow-tool-schema' import { deployWorkflow, loadWorkflowFromNormalizedTables } from '@/lib/workflows/persistence/utils' +import { hasValidStartBlockInState } from '@/lib/workflows/triggers/trigger-utils' import { validateWorkflowPermissions } from '@/lib/workflows/utils' -import { - hasValidStartBlock, - isValidStartBlockType, -} from '@/lib/workflows/triggers/trigger-utils' import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils' const logger = createLogger('WorkflowDeployAPI') +/** + * Check if a workflow has a valid start block by loading from database + */ +async function hasValidStartBlock(workflowId: string): Promise { + try { + const normalizedData = await loadWorkflowFromNormalizedTables(workflowId) + return hasValidStartBlockInState(normalizedData) + } catch (error) { + logger.warn('Error checking for start block:', error) + return false + } +} + export const dynamic = 'force-dynamic' export const runtime = 'nodejs' @@ -26,58 +40,12 @@ async function generateMcpToolSchema(workflowId: string): Promise { - return isValidStartBlockType(block?.type) - }) as any - - if (!startBlock?.subBlocks?.inputFormat?.value) { + const inputFormat = extractInputFormatFromBlocks(normalizedData.blocks) + if (!inputFormat || inputFormat.length === 0) { return { type: 'object', properties: {} } } - const inputFormat = startBlock.subBlocks.inputFormat.value - if (!Array.isArray(inputFormat) || inputFormat.length === 0) { - return { type: 'object', properties: {} } - } - - const properties: Record = {} - const required: string[] = [] - - for (const field of inputFormat) { - if (!field?.name || typeof field.name !== 'string' || !field.name.trim()) continue - - const fieldName = field.name.trim() - let jsonType = 'string' - switch (field.type) { - case 'number': - jsonType = 'number' - break - case 'boolean': - jsonType = 'boolean' - break - case 'object': - jsonType = 'object' - break - case 'array': - case 'files': - jsonType = 'array' - break - default: - jsonType = 'string' - } - - properties[fieldName] = { - type: jsonType, - description: fieldName, - } - required.push(fieldName) - } - - return { - type: 'object', - properties, - required: required.length > 0 ? required : undefined, - } + return generateToolInputSchema(inputFormat) as unknown as Record } catch (error) { logger.warn('Error generating MCP tool schema:', error) return { type: 'object', properties: {} } diff --git a/apps/sim/app/api/workflows/[id]/deployments/[version]/activate/route.ts b/apps/sim/app/api/workflows/[id]/deployments/[version]/activate/route.ts index 18b48c8c26..158bcc3dc6 100644 --- a/apps/sim/app/api/workflows/[id]/deployments/[version]/activate/route.ts +++ b/apps/sim/app/api/workflows/[id]/deployments/[version]/activate/route.ts @@ -3,11 +3,12 @@ import { and, eq } from 'drizzle-orm' import type { NextRequest } from 'next/server' import { generateRequestId } from '@/lib/core/utils/request' import { createLogger } from '@/lib/logs/console/logger' -import { validateWorkflowPermissions } from '@/lib/workflows/utils' import { - hasValidStartBlockInState, - isValidStartBlockType, -} from '@/lib/workflows/triggers/trigger-utils' + extractInputFormatFromBlocks, + generateToolInputSchema, +} from '@/lib/mcp/workflow-tool-schema' +import { hasValidStartBlockInState } from '@/lib/workflows/triggers/trigger-utils' +import { validateWorkflowPermissions } from '@/lib/workflows/utils' import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils' const logger = createLogger('WorkflowActivateDeploymentAPI') @@ -24,58 +25,12 @@ function generateMcpToolSchemaFromState(state: any): Record { return { type: 'object', properties: {} } } - // Find the start block in the deployed state - const startBlock = Object.values(state.blocks).find((block: any) => { - return isValidStartBlockType(block?.type) - }) as any - - if (!startBlock?.subBlocks?.inputFormat?.value) { - return { type: 'object', properties: {} } - } - - const inputFormat = startBlock.subBlocks.inputFormat.value - if (!Array.isArray(inputFormat) || inputFormat.length === 0) { + const inputFormat = extractInputFormatFromBlocks(state.blocks) + if (!inputFormat || inputFormat.length === 0) { return { type: 'object', properties: {} } } - const properties: Record = {} - const required: string[] = [] - - for (const field of inputFormat) { - if (!field?.name || typeof field.name !== 'string' || !field.name.trim()) continue - - const fieldName = field.name.trim() - let jsonType = 'string' - switch (field.type) { - case 'number': - jsonType = 'number' - break - case 'boolean': - jsonType = 'boolean' - break - case 'object': - jsonType = 'object' - break - case 'array': - case 'files': - jsonType = 'array' - break - default: - jsonType = 'string' - } - - properties[fieldName] = { - type: jsonType, - description: fieldName, - } - required.push(fieldName) - } - - return { - type: 'object', - properties, - required: required.length > 0 ? required : undefined, - } + return generateToolInputSchema(inputFormat) as unknown as Record } catch (error) { logger.warn('Error generating MCP tool schema from state:', error) return { type: 'object', properties: {} } diff --git a/apps/sim/app/api/workflows/[id]/deployments/[version]/revert/route.ts b/apps/sim/app/api/workflows/[id]/deployments/[version]/revert/route.ts index 74e543a419..d331d8be14 100644 --- a/apps/sim/app/api/workflows/[id]/deployments/[version]/revert/route.ts +++ b/apps/sim/app/api/workflows/[id]/deployments/[version]/revert/route.ts @@ -4,12 +4,13 @@ import type { NextRequest } from 'next/server' import { env } from '@/lib/core/config/env' import { generateRequestId } from '@/lib/core/utils/request' import { createLogger } from '@/lib/logs/console/logger' +import { + extractInputFormatFromBlocks, + generateToolInputSchema, +} from '@/lib/mcp/workflow-tool-schema' import { saveWorkflowToNormalizedTables } from '@/lib/workflows/persistence/utils' +import { hasValidStartBlockInState } from '@/lib/workflows/triggers/trigger-utils' import { validateWorkflowPermissions } from '@/lib/workflows/utils' -import { - hasValidStartBlockInState, - isValidStartBlockType, -} from '@/lib/workflows/triggers/trigger-utils' import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils' const logger = createLogger('RevertToDeploymentVersionAPI') @@ -26,58 +27,12 @@ function generateMcpToolSchemaFromState(state: any): Record { return { type: 'object', properties: {} } } - // Find the start block in the deployed state - const startBlock = Object.values(state.blocks).find((block: any) => { - return isValidStartBlockType(block?.type) - }) as any - - if (!startBlock?.subBlocks?.inputFormat?.value) { + const inputFormat = extractInputFormatFromBlocks(state.blocks) + if (!inputFormat || inputFormat.length === 0) { return { type: 'object', properties: {} } } - const inputFormat = startBlock.subBlocks.inputFormat.value - if (!Array.isArray(inputFormat) || inputFormat.length === 0) { - return { type: 'object', properties: {} } - } - - const properties: Record = {} - const required: string[] = [] - - for (const field of inputFormat) { - if (!field?.name || typeof field.name !== 'string' || !field.name.trim()) continue - - const fieldName = field.name.trim() - let jsonType = 'string' - switch (field.type) { - case 'number': - jsonType = 'number' - break - case 'boolean': - jsonType = 'boolean' - break - case 'object': - jsonType = 'object' - break - case 'array': - case 'files': - jsonType = 'array' - break - default: - jsonType = 'string' - } - - properties[fieldName] = { - type: jsonType, - description: fieldName, - } - required.push(fieldName) - } - - return { - type: 'object', - properties, - required: required.length > 0 ? required : undefined, - } + return generateToolInputSchema(inputFormat) as unknown as Record } catch (error) { logger.warn('Error generating MCP tool schema from state:', error) return { type: 'object', properties: {} } diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx index 36ac50b6f8..a3a9c7474d 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx @@ -118,11 +118,18 @@ function extractInputFormat( /** * Generate JSON Schema from input format using the shared utility + * Optionally applies custom descriptions from the UI */ function generateParameterSchema( - inputFormat: Array<{ name: string; type: string }> + inputFormat: Array<{ name: string; type: string }>, + customDescriptions?: Record ): Record { - return generateToolInputSchema(inputFormat) as unknown as Record + // Convert to InputFormatField with descriptions + const fieldsWithDescriptions = inputFormat.map((field) => ({ + ...field, + description: customDescriptions?.[field.name]?.trim() || undefined, + })) + return generateToolInputSchema(fieldsWithDescriptions) as unknown as Record } /** @@ -461,13 +468,18 @@ export function McpToolDeploy({ return extractInputFormat(blocks) }, [starterBlockId, subBlockValues, blocks]) - const parameterSchema = useMemo(() => generateParameterSchema(inputFormat), [inputFormat]) - const [selectedServer, setSelectedServer] = useState(null) const [toolName, setToolName] = useState('') const [toolDescription, setToolDescription] = useState('') const [showServerSelector, setShowServerSelector] = useState(false) const [showParameterSchema, setShowParameterSchema] = useState(false) + // Track custom descriptions for each parameter + const [parameterDescriptions, setParameterDescriptions] = useState>({}) + + const parameterSchema = useMemo( + () => generateParameterSchema(inputFormat, parameterDescriptions), + [inputFormat, parameterDescriptions] + ) // Track tools data from each server using state instead of hooks in a loop const [serverToolsMap, setServerToolsMap] = useState< @@ -509,6 +521,32 @@ export function McpToolDeploy({ return serversWithThisWorkflow.filter(({ tool }) => hasParameterMismatch(tool, inputFormat)) }, [serversWithThisWorkflow, inputFormat]) + // Load existing parameter descriptions from the first deployed tool + useEffect(() => { + if (serversWithThisWorkflow.length > 0) { + const existingTool = serversWithThisWorkflow[0].tool + const schema = existingTool.parameterSchema as Record | undefined + const properties = schema?.properties as Record | undefined + + if (properties) { + const descriptions: Record = {} + for (const [name, prop] of Object.entries(properties)) { + // Only use description if it differs from the field name (i.e., it's custom) + if ( + prop.description && + prop.description !== name && + prop.description !== 'Array of file objects' + ) { + descriptions[name] = prop.description + } + } + if (Object.keys(descriptions).length > 0) { + setParameterDescriptions(descriptions) + } + } + } + }, [serversWithThisWorkflow]) + // Reset form when selected server changes useEffect(() => { if (selectedServer) { @@ -668,17 +706,33 @@ export function McpToolDeploy({ parameters.

) : ( -
+
{inputFormat.map((field, index) => ( -
- - {field.name} - - - {field.type} - +
+
+ + {field.name} + + + {field.type} + +
+ + setParameterDescriptions((prev) => ({ + ...prev, + [field.name]: e.target.value, + })) + } + placeholder={`Describe what "${field.name}" is for...`} + className='h-[32px] text-[12px]' + />
))} +

+ Descriptions help MCP clients understand what each parameter is for. +

)}
diff --git a/apps/sim/lib/mcp/serve-auth.ts b/apps/sim/lib/mcp/serve-auth.ts index 4edbbf2d3d..a4a4768439 100644 --- a/apps/sim/lib/mcp/serve-auth.ts +++ b/apps/sim/lib/mcp/serve-auth.ts @@ -4,7 +4,6 @@ import { eq } from 'drizzle-orm' import type { NextRequest } from 'next/server' import { checkHybridAuth } from '@/lib/auth/hybrid' import { createLogger } from '@/lib/logs/console/logger' -import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils' const logger = createLogger('McpServeAuth') diff --git a/apps/sim/lib/mcp/workflow-mcp-server.ts b/apps/sim/lib/mcp/workflow-mcp-server.ts new file mode 100644 index 0000000000..53a6679f50 --- /dev/null +++ b/apps/sim/lib/mcp/workflow-mcp-server.ts @@ -0,0 +1,399 @@ +/** + * Workflow MCP Server + * + * Creates an MCP server using the official @modelcontextprotocol/sdk + * that exposes workflows as tools via a Next.js-compatible transport. + */ + +import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js' +import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js' +import type { JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js' +import { db } from '@sim/db' +import { workflow, workflowMcpTool } from '@sim/db/schema' +import { eq } from 'drizzle-orm' +import { z } from 'zod' +import { getBaseUrl } from '@/lib/core/utils/urls' +import { createLogger } from '@/lib/logs/console/logger' +import { fileItemZodSchema } from '@/lib/mcp/workflow-tool-schema' + +const logger = createLogger('WorkflowMcpServer') + +/** + * Convert stored JSON schema to Zod schema. + * Uses fileItemZodSchema from workflow-tool-schema for file arrays. + */ +function jsonSchemaToZodShape(schema: Record | null): z.ZodRawShape | undefined { + if (!schema || schema.type !== 'object') { + return undefined + } + + const properties = schema.properties as + | Record + | undefined + if (!properties || Object.keys(properties).length === 0) { + return undefined + } + + const shape: z.ZodRawShape = {} + const required = (schema.required as string[] | undefined) || [] + + for (const [key, prop] of Object.entries(properties)) { + let zodType: z.ZodTypeAny + + // Check if this array has items (file arrays have items.type === 'object') + const hasObjectItems = + prop.type === 'array' && + prop.items && + typeof prop.items === 'object' && + (prop.items as Record).type === 'object' + + switch (prop.type) { + case 'string': + zodType = z.string() + break + case 'number': + zodType = z.number() + break + case 'boolean': + zodType = z.boolean() + break + case 'array': + if (hasObjectItems) { + // File arrays - use the shared file item schema + zodType = z.array(fileItemZodSchema) + } else { + zodType = z.array(z.any()) + } + break + case 'object': + zodType = z.record(z.any()) + break + default: + zodType = z.any() + } + + if (prop.description) { + zodType = zodType.describe(prop.description) + } + + if (!required.includes(key)) { + zodType = zodType.optional() + } + + shape[key] = zodType + } + + return Object.keys(shape).length > 0 ? shape : undefined +} + +interface WorkflowTool { + id: string + toolName: string + toolDescription: string | null + parameterSchema: Record | null + workflowId: string + isEnabled: boolean +} + +interface ServerContext { + serverId: string + serverName: string + userId: string + workspaceId: string + apiKey?: string | null +} + +/** + * A simple transport for handling single request/response cycles in Next.js + * This transport is designed for stateless request handling where each + * request creates a new server instance. + */ +class NextJsTransport implements Transport { + private responseMessage: JSONRPCMessage | null = null + private resolveResponse: ((message: JSONRPCMessage) => void) | null = null + + onclose?: () => void + onerror?: (error: Error) => void + onmessage?: (message: JSONRPCMessage) => void + + async start(): Promise { + // No-op for stateless transport + } + + async close(): Promise { + this.onclose?.() + } + + async send(message: JSONRPCMessage): Promise { + this.responseMessage = message + this.resolveResponse?.(message) + } + + /** + * Injects a message into the transport as if it was received from the client + */ + receiveMessage(message: JSONRPCMessage): void { + this.onmessage?.(message) + } + + /** + * Waits for the server to send a response + */ + waitForResponse(): Promise { + if (this.responseMessage) { + return Promise.resolve(this.responseMessage) + } + return new Promise((resolve) => { + this.resolveResponse = resolve + }) + } +} + +/** + * Creates and configures an MCP server with workflow tools + */ +async function createConfiguredMcpServer(context: ServerContext): Promise { + const { serverId, serverName, apiKey } = context + + // Create the MCP server using the SDK + const server = new McpServer({ + name: serverName, + version: '1.0.0', + }) + + // Load tools from the database + const tools = await db + .select({ + id: workflowMcpTool.id, + toolName: workflowMcpTool.toolName, + toolDescription: workflowMcpTool.toolDescription, + parameterSchema: workflowMcpTool.parameterSchema, + workflowId: workflowMcpTool.workflowId, + isEnabled: workflowMcpTool.isEnabled, + }) + .from(workflowMcpTool) + .where(eq(workflowMcpTool.serverId, serverId)) + + // Register each enabled tool + for (const tool of tools.filter((t) => t.isEnabled)) { + const zodSchema = jsonSchemaToZodShape(tool.parameterSchema as Record | null) + + if (zodSchema) { + // Tool with parameters - callback receives (args, extra) + server.tool( + tool.toolName, + tool.toolDescription || `Execute workflow: ${tool.toolName}`, + zodSchema, + async (args) => { + return executeWorkflowTool(tool as WorkflowTool, args, apiKey) + } + ) + } else { + // Tool without parameters - callback only receives (extra) + server.tool( + tool.toolName, + tool.toolDescription || `Execute workflow: ${tool.toolName}`, + async () => { + return executeWorkflowTool(tool as WorkflowTool, {}, apiKey) + } + ) + } + } + + logger.info( + `Created MCP server "${serverName}" with ${tools.filter((t) => t.isEnabled).length} tools` + ) + + return server +} + +/** + * Executes a workflow tool and returns the result + */ +async function executeWorkflowTool( + tool: WorkflowTool, + args: Record, + apiKey?: string | null +): Promise<{ + content: Array<{ type: 'text'; text: string }> + isError?: boolean +}> { + logger.info(`Executing workflow ${tool.workflowId} via MCP tool ${tool.toolName}`) + + try { + // Verify workflow is deployed + const [workflowRecord] = await db + .select({ id: workflow.id, isDeployed: workflow.isDeployed }) + .from(workflow) + .where(eq(workflow.id, tool.workflowId)) + .limit(1) + + if (!workflowRecord || !workflowRecord.isDeployed) { + return { + content: [{ type: 'text', text: JSON.stringify({ error: 'Workflow is not deployed' }) }], + isError: true, + } + } + + // Execute the workflow + const baseUrl = getBaseUrl() + const executeUrl = `${baseUrl}/api/workflows/${tool.workflowId}/execute` + + const executeHeaders: Record = { + 'Content-Type': 'application/json', + } + + if (apiKey) { + executeHeaders['X-API-Key'] = apiKey + } + + const executeResponse = await fetch(executeUrl, { + method: 'POST', + headers: executeHeaders, + body: JSON.stringify({ + input: args, + triggerType: 'mcp', + }), + }) + + const executeResult = await executeResponse.json() + + if (!executeResponse.ok) { + return { + content: [ + { + type: 'text', + text: JSON.stringify({ error: executeResult.error || 'Workflow execution failed' }), + }, + ], + isError: true, + } + } + + return { + content: [ + { + type: 'text', + text: JSON.stringify(executeResult.output || executeResult, null, 2), + }, + ], + isError: !executeResult.success, + } + } catch (error) { + logger.error(`Error executing workflow ${tool.workflowId}:`, error) + return { + content: [{ type: 'text', text: JSON.stringify({ error: 'Tool execution failed' }) }], + isError: true, + } + } +} + +/** + * Handles an MCP JSON-RPC request using the SDK + */ +export async function handleMcpRequest( + context: ServerContext, + request: Request +): Promise { + try { + // Parse the incoming JSON-RPC message + const body = await request.json() + const message = body as JSONRPCMessage + + // Create transport and server + const transport = new NextJsTransport() + const server = await createConfiguredMcpServer(context) + + // Connect server to transport + await server.connect(transport) + + // Inject the received message + transport.receiveMessage(message) + + // Wait for the response + const response = await transport.waitForResponse() + + // Clean up + await server.close() + + return new Response(JSON.stringify(response), { + status: 200, + headers: { + 'Content-Type': 'application/json', + 'X-MCP-Server-Name': context.serverName, + }, + }) + } catch (error) { + logger.error('Error handling MCP request:', error) + + return new Response( + JSON.stringify({ + jsonrpc: '2.0', + id: null, + error: { + code: -32603, + message: 'Internal error', + }, + }), + { + status: 500, + headers: { 'Content-Type': 'application/json' }, + } + ) + } +} + +/** + * Creates an SSE stream for MCP notifications (used for GET requests) + */ +export function createMcpSseStream(context: ServerContext): ReadableStream { + const encoder = new TextEncoder() + let isStreamClosed = false + + return new ReadableStream({ + async start(controller) { + const sendEvent = (event: string, data: unknown) => { + if (isStreamClosed) return + try { + const message = `event: ${event}\ndata: ${JSON.stringify(data)}\n\n` + controller.enqueue(encoder.encode(message)) + } catch { + isStreamClosed = true + } + } + + // Send initial connection event + sendEvent('open', { type: 'connection', status: 'connected' }) + + // Send server capabilities + sendEvent('message', { + jsonrpc: '2.0', + method: 'notifications/initialized', + params: { + protocolVersion: '2024-11-05', + capabilities: { + tools: {}, + }, + serverInfo: { + name: context.serverName, + version: '1.0.0', + }, + }, + }) + + // Keep connection alive with periodic pings + const pingInterval = setInterval(() => { + if (isStreamClosed) { + clearInterval(pingInterval) + return + } + sendEvent('ping', { timestamp: Date.now() }) + }, 30000) + }, + + cancel() { + isStreamClosed = true + logger.info(`SSE connection closed for server ${context.serverId}`) + }, + }) +} diff --git a/apps/sim/lib/mcp/workflow-tool-schema.ts b/apps/sim/lib/mcp/workflow-tool-schema.ts index e54482fbd3..1876ade051 100644 --- a/apps/sim/lib/mcp/workflow-tool-schema.ts +++ b/apps/sim/lib/mcp/workflow-tool-schema.ts @@ -1,3 +1,4 @@ +import { z } from 'zod' import type { InputFormatField } from '@/lib/workflows/types' /** @@ -23,7 +24,70 @@ export interface McpToolDefinition { } /** - * Map InputFormatField type to JSON Schema type + * File item Zod schema for MCP file inputs. + * This is the single source of truth for file structure. + */ +export const fileItemZodSchema = z.object({ + name: z.string().describe('File name'), + data: z.string().describe('Base64 encoded file content'), + mimeType: z.string().describe('MIME type of the file'), +}) + +/** + * Convert InputFormatField type to Zod schema + */ +function fieldTypeToZod(fieldType: string | undefined, isRequired: boolean): z.ZodTypeAny { + let zodType: z.ZodTypeAny + + switch (fieldType) { + case 'string': + zodType = z.string() + break + case 'number': + zodType = z.number() + break + case 'boolean': + zodType = z.boolean() + break + case 'object': + zodType = z.record(z.any()) + break + case 'array': + zodType = z.array(z.any()) + break + case 'files': + zodType = z.array(fileItemZodSchema) + break + default: + zodType = z.string() + } + + return isRequired ? zodType : zodType.optional() +} + +/** + * Generate Zod schema shape from InputFormatField array. + * This is used directly by the MCP server for tool registration. + */ +export function generateToolZodSchema(inputFormat: InputFormatField[]): z.ZodRawShape | undefined { + if (!inputFormat || inputFormat.length === 0) { + return undefined + } + + const shape: z.ZodRawShape = {} + + for (const field of inputFormat) { + if (!field.name) continue + + const zodType = fieldTypeToZod(field.type, true) + shape[field.name] = field.name ? zodType.describe(field.name) : zodType + } + + return Object.keys(shape).length > 0 ? shape : undefined +} + +/** + * Map InputFormatField type to JSON Schema type (for database storage) */ function mapFieldTypeToJsonSchemaType(fieldType: string | undefined): string { switch (fieldType) { @@ -77,7 +141,8 @@ export function generateToolInputSchema(inputFormat: InputFormatField[]): McpToo const property: McpToolProperty = { type: fieldType, - description: fieldName, // Use field name as description by default + // Use custom description if provided, otherwise use field name + description: field.description?.trim() || fieldName, } // Handle array types @@ -92,7 +157,10 @@ export function generateToolInputSchema(inputFormat: InputFormatField[]): McpToo size: { type: 'number', description: 'File size in bytes' }, }, } - property.description = 'Array of file objects' + // Use custom description if provided, otherwise use default + if (!field.description?.trim()) { + property.description = 'Array of file objects' + } } else { property.items = { type: 'string' } } @@ -129,21 +197,33 @@ export function generateToolDefinition( } } +/** + * Valid start block types that can have input format + */ +const VALID_START_BLOCK_TYPES = [ + 'starter', + 'start', + 'start_trigger', + 'api', + 'api_trigger', + 'input_trigger', +] + /** * Extract input format from a workflow's blocks. - * Looks for the starter block and extracts its inputFormat configuration. + * Looks for any valid start block and extracts its inputFormat configuration. */ export function extractInputFormatFromBlocks( blocks: Record ): InputFormatField[] | null { - // Look for starter or input_trigger block + // Look for any valid start block for (const [, block] of Object.entries(blocks)) { if (!block || typeof block !== 'object') continue const blockObj = block as Record - const blockType = blockObj.type + const blockType = blockObj.type as string - if (blockType === 'starter' || blockType === 'input_trigger') { + if (VALID_START_BLOCK_TYPES.includes(blockType)) { // Try to get inputFormat from subBlocks const subBlocks = blockObj.subBlocks as Record | undefined if (subBlocks?.inputFormat) { diff --git a/apps/sim/lib/workflows/triggers/trigger-utils.ts b/apps/sim/lib/workflows/triggers/trigger-utils.ts index 56af72990b..64c9343e47 100644 --- a/apps/sim/lib/workflows/triggers/trigger-utils.ts +++ b/apps/sim/lib/workflows/triggers/trigger-utils.ts @@ -7,7 +7,6 @@ import { import { getAllBlocks, getBlock } from '@/blocks' import type { BlockConfig } from '@/blocks/types' import { getTrigger } from '@/triggers' -import { loadWorkflowFromNormalizedTables } from '@/lib/workflows/persistence/utils' const logger = createLogger('TriggerUtils') @@ -48,19 +47,6 @@ export function hasValidStartBlockInState(state: any): boolean { return !!startBlock } -/** - * Check if a workflow has a valid start block by loading from database - */ -export async function hasValidStartBlock(workflowId: string): Promise { - try { - const normalizedData = await loadWorkflowFromNormalizedTables(workflowId) - return hasValidStartBlockInState(normalizedData) - } catch (error) { - logger.warn('Error checking for start block:', error) - return false - } -} - /** * Generates mock data based on the output type definition */ diff --git a/apps/sim/lib/workflows/types.ts b/apps/sim/lib/workflows/types.ts index f288e2d4a9..6eb4b547ee 100644 --- a/apps/sim/lib/workflows/types.ts +++ b/apps/sim/lib/workflows/types.ts @@ -1,6 +1,7 @@ export interface InputFormatField { name?: string type?: 'string' | 'number' | 'boolean' | 'object' | 'array' | 'files' | string + description?: string value?: unknown } diff --git a/apps/sim/package.json b/apps/sim/package.json index b7aff8168c..b34c4a80fe 100644 --- a/apps/sim/package.json +++ b/apps/sim/package.json @@ -8,7 +8,7 @@ "node": ">=20.0.0" }, "scripts": { - "dev": "next dev --port 7321", + "dev": "next dev --port 3000", "dev:webpack": "next dev --webpack", "dev:sockets": "bun run socket-server/index.ts", "dev:full": "concurrently -n \"App,Realtime\" -c \"cyan,magenta\" \"bun run dev\" \"bun run dev:sockets\"", From fe4f895386a6843417bde0b809b004737cc1e16d Mon Sep 17 00:00:00 2001 From: "priyanshu.solanki" Date: Thu, 18 Dec 2025 13:03:29 -0700 Subject: [PATCH 11/27] using normalised input schema function --- apps/sim/lib/mcp/workflow-tool-schema.ts | 35 +++++++----------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/apps/sim/lib/mcp/workflow-tool-schema.ts b/apps/sim/lib/mcp/workflow-tool-schema.ts index 1876ade051..80100d1269 100644 --- a/apps/sim/lib/mcp/workflow-tool-schema.ts +++ b/apps/sim/lib/mcp/workflow-tool-schema.ts @@ -1,4 +1,6 @@ import { z } from 'zod' +import { normalizeInputFormatValue } from '@/lib/workflows/input-format-utils' +import { isValidStartBlockType } from '@/lib/workflows/triggers/trigger-utils' import type { InputFormatField } from '@/lib/workflows/types' /** @@ -197,18 +199,6 @@ export function generateToolDefinition( } } -/** - * Valid start block types that can have input format - */ -const VALID_START_BLOCK_TYPES = [ - 'starter', - 'start', - 'start_trigger', - 'api', - 'api_trigger', - 'input_trigger', -] - /** * Extract input format from a workflow's blocks. * Looks for any valid start block and extracts its inputFormat configuration. @@ -223,23 +213,18 @@ export function extractInputFormatFromBlocks( const blockObj = block as Record const blockType = blockObj.type as string - if (VALID_START_BLOCK_TYPES.includes(blockType)) { - // Try to get inputFormat from subBlocks - const subBlocks = blockObj.subBlocks as Record | undefined - if (subBlocks?.inputFormat) { - const inputFormatSubBlock = subBlocks.inputFormat as Record - const value = inputFormatSubBlock.value - if (Array.isArray(value)) { - return value as InputFormatField[] - } - } + if (isValidStartBlockType(blockType)) { + // Try to get inputFormat from subBlocks.inputFormat.value + const subBlocks = blockObj.subBlocks as Record | undefined + const subBlockValue = subBlocks?.inputFormat?.value // Try legacy config.params.inputFormat const config = blockObj.config as Record | undefined const params = config?.params as Record | undefined - if (params?.inputFormat && Array.isArray(params.inputFormat)) { - return params.inputFormat as InputFormatField[] - } + const paramsValue = params?.inputFormat + + const normalized = normalizeInputFormatValue(subBlockValue ?? paramsValue) + return normalized.length > 0 ? normalized : null } } From 4bb9a8de150c9bda6caba0aadb39691c080d02cb Mon Sep 17 00:00:00 2001 From: Siddharth Ganesan Date: Thu, 18 Dec 2025 17:05:29 -0800 Subject: [PATCH 12/27] ui fixes part 1 --- .../sim/app/api/mcp/workflow-servers/route.ts | 34 +- .../components/mcp-tool/mcp-tool.tsx | 735 +++++------------- .../workflow-mcp-servers.tsx | 373 +++------ .../settings-modal/settings-modal.tsx | 4 +- .../sim/hooks/queries/workflow-mcp-servers.ts | 1 + 5 files changed, 356 insertions(+), 791 deletions(-) diff --git a/apps/sim/app/api/mcp/workflow-servers/route.ts b/apps/sim/app/api/mcp/workflow-servers/route.ts index 8da34710e7..99b5837bb0 100644 --- a/apps/sim/app/api/mcp/workflow-servers/route.ts +++ b/apps/sim/app/api/mcp/workflow-servers/route.ts @@ -1,6 +1,6 @@ import { db } from '@sim/db' -import { workflowMcpServer } from '@sim/db/schema' -import { eq, sql } from 'drizzle-orm' +import { workflowMcpServer, workflowMcpTool } from '@sim/db/schema' +import { eq, inArray, sql } from 'drizzle-orm' import type { NextRequest } from 'next/server' import { createLogger } from '@/lib/logs/console/logger' import { getParsedBody, withMcpAuth } from '@/lib/mcp/middleware' @@ -38,10 +38,38 @@ export const GET = withMcpAuth('read')( .from(workflowMcpServer) .where(eq(workflowMcpServer.workspaceId, workspaceId)) + // Fetch all tools for these servers + const serverIds = servers.map((s) => s.id) + const tools = + serverIds.length > 0 + ? await db + .select({ + serverId: workflowMcpTool.serverId, + toolName: workflowMcpTool.toolName, + }) + .from(workflowMcpTool) + .where(inArray(workflowMcpTool.serverId, serverIds)) + : [] + + // Group tool names by server + const toolNamesByServer: Record = {} + for (const tool of tools) { + if (!toolNamesByServer[tool.serverId]) { + toolNamesByServer[tool.serverId] = [] + } + toolNamesByServer[tool.serverId].push(tool.toolName) + } + + // Attach tool names to servers + const serversWithToolNames = servers.map((server) => ({ + ...server, + toolNames: toolNamesByServer[server.id] || [], + })) + logger.info( `[${requestId}] Listed ${servers.length} workflow MCP servers for workspace ${workspaceId}` ) - return createMcpSuccessResponse({ servers }) + return createMcpSuccessResponse({ servers: serversWithToolNames }) } catch (error) { logger.error(`[${requestId}] Error listing workflow MCP servers:`, error) return createMcpErrorResponse( diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx index a3a9c7474d..ba7f542450 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/mcp-tool/mcp-tool.tsx @@ -1,34 +1,24 @@ 'use client' import { useCallback, useEffect, useMemo, useState } from 'react' -import { - AlertTriangle, - ChevronDown, - ChevronRight, - Plus, - RefreshCw, - Server, - Trash2, -} from 'lucide-react' +import { Check, Server } from 'lucide-react' import { useParams } from 'next/navigation' import { Badge, - Button, - Input as EmcnInput, + Input, Label, Popover, PopoverContent, PopoverItem, PopoverTrigger, + Textarea, } from '@/components/emcn' import { Skeleton } from '@/components/ui' -import { cn } from '@/lib/core/utils/cn' import { createLogger } from '@/lib/logs/console/logger' import { generateToolInputSchema, sanitizeToolName } from '@/lib/mcp/workflow-tool-schema' import { useAddWorkflowMcpTool, useDeleteWorkflowMcpTool, - useUpdateWorkflowMcpTool, useWorkflowMcpServers, useWorkflowMcpTools, type WorkflowMcpServer, @@ -117,53 +107,21 @@ function extractInputFormat( } /** - * Generate JSON Schema from input format using the shared utility - * Optionally applies custom descriptions from the UI + * Generate JSON Schema from input format with optional descriptions */ function generateParameterSchema( inputFormat: Array<{ name: string; type: string }>, - customDescriptions?: Record + descriptions: Record ): Record { - // Convert to InputFormatField with descriptions const fieldsWithDescriptions = inputFormat.map((field) => ({ ...field, - description: customDescriptions?.[field.name]?.trim() || undefined, + description: descriptions[field.name]?.trim() || undefined, })) return generateToolInputSchema(fieldsWithDescriptions) as unknown as Record } -/** - * Extract parameter names from a tool's parameter schema - */ -function getToolParameterNames(schema: Record): string[] { - const properties = schema.properties as Record | undefined - if (!properties) return [] - return Object.keys(properties) -} - -/** - * Check if the tool's parameters differ from the current workflow's input format - */ -function hasParameterMismatch( - tool: WorkflowMcpTool, - currentInputFormat: Array<{ name: string; type: string }> -): boolean { - const toolParams = getToolParameterNames(tool.parameterSchema as Record) - const currentParams = currentInputFormat.map((f) => f.name) - - if (toolParams.length !== currentParams.length) return true - - const toolParamSet = new Set(toolParams) - for (const param of currentParams) { - if (!toolParamSet.has(param)) return true - } - - return false -} - /** * Component to query tools for a single server and report back via callback. - * This pattern avoids calling hooks in a loop. */ function ServerToolsQuery({ workspaceId, @@ -183,186 +141,7 @@ function ServerToolsQuery({ onData(server.id, tool, isLoading) }, [tools, isLoading, workflowId, server.id, onData]) - return null // This component doesn't render anything -} - -interface ToolOnServerProps { - server: WorkflowMcpServer - tool: WorkflowMcpTool - workspaceId: string - currentInputFormat: Array<{ name: string; type: string }> - currentParameterSchema: Record - workflowDescription: string | null | undefined - onRemoved: (serverId: string) => void - onUpdated: () => void -} - -function ToolOnServer({ - server, - tool, - workspaceId, - currentInputFormat, - currentParameterSchema, - workflowDescription, - onRemoved, - onUpdated, -}: ToolOnServerProps) { - const deleteToolMutation = useDeleteWorkflowMcpTool() - const updateToolMutation = useUpdateWorkflowMcpTool() - const [showConfirm, setShowConfirm] = useState(false) - const [showDetails, setShowDetails] = useState(false) - - const needsUpdate = hasParameterMismatch(tool, currentInputFormat) - const toolParams = getToolParameterNames(tool.parameterSchema as Record) - - const handleRemove = async () => { - try { - await deleteToolMutation.mutateAsync({ - workspaceId, - serverId: server.id, - toolId: tool.id, - }) - onRemoved(server.id) - } catch (error) { - logger.error('Failed to remove tool:', error) - } - } - - const handleUpdate = async () => { - try { - await updateToolMutation.mutateAsync({ - workspaceId, - serverId: server.id, - toolId: tool.id, - toolDescription: workflowDescription || `Execute workflow`, - parameterSchema: currentParameterSchema, - }) - onUpdated() - logger.info(`Updated tool ${tool.id} with new parameters`) - } catch (error) { - logger.error('Failed to update tool:', error) - } - } - - if (showConfirm) { - return ( -
- Remove from {server.name}? -
- - -
-
- ) - } - - return ( -
-
setShowDetails(!showDetails)} - > -
- {showDetails ? ( - - ) : ( - - )} - {server.name} - {server.isPublished && ( - - Published - - )} - {needsUpdate && ( - - - Needs Update - - )} -
-
e.stopPropagation()}> - {needsUpdate && ( - - )} - -
-
- - {showDetails && ( -
-
-
- Tool Name - - {tool.toolName} - -
-
- - Description - - - {tool.toolDescription || '—'} - -
-
- - Parameters ({toolParams.length}) - -
- {toolParams.length === 0 ? ( - None - ) : ( - toolParams.map((param) => ( - - {param} - - )) - )} -
-
-
-
- )} -
- ) + return null } export function McpToolDeploy({ @@ -381,20 +160,18 @@ export function McpToolDeploy({ refetch: refetchServers, } = useWorkflowMcpServers(workspaceId) const addToolMutation = useAddWorkflowMcpTool() + const deleteToolMutation = useDeleteWorkflowMcpTool() - // Get workflow blocks const blocks = useWorkflowStore((state) => state.blocks) - // Find the starter block ID to subscribe to its inputFormat changes const starterBlockId = useMemo(() => { for (const [blockId, block] of Object.entries(blocks)) { if (!block || typeof block !== 'object') continue const blockType = (block as { type?: string }).type - // Check for all possible start/trigger block types if ( blockType === 'starter' || blockType === 'start' || - blockType === 'start_trigger' || // This is the unified start block type + blockType === 'start_trigger' || blockType === 'api' || blockType === 'api_trigger' || blockType === 'input_trigger' @@ -405,15 +182,11 @@ export function McpToolDeploy({ return null }, [blocks]) - // Subscribe to the inputFormat value in SubBlockStore for reactivity - // Use workflowId prop directly (not activeWorkflowId from registry) to ensure we get the correct workflow's data const subBlockValues = useSubBlockStore((state) => workflowId ? (state.workflowValues[workflowId] ?? {}) : {} ) - // Extract and normalize input format - now reactive to SubBlockStore changes const inputFormat = useMemo(() => { - // First try to get from SubBlockStore (where runtime values are stored) if (starterBlockId && subBlockValues[starterBlockId]) { const inputFormatValue = subBlockValues[starterBlockId].inputFormat @@ -437,7 +210,6 @@ export function McpToolDeploy({ } } - // Fallback: try to get from block structure (for initial load or backwards compatibility) if (starterBlockId && blocks[starterBlockId]) { const startBlock = blocks[starterBlockId] const subBlocksValue = startBlock?.subBlocks?.inputFormat?.value as unknown @@ -464,16 +236,14 @@ export function McpToolDeploy({ } } - // Last fallback: use extractInputFormat helper return extractInputFormat(blocks) }, [starterBlockId, subBlockValues, blocks]) - const [selectedServer, setSelectedServer] = useState(null) - const [toolName, setToolName] = useState('') - const [toolDescription, setToolDescription] = useState('') + const [toolName, setToolName] = useState(() => sanitizeToolName(workflowName)) + const [toolDescription, setToolDescription] = useState( + () => workflowDescription || `Execute ${workflowName} workflow` + ) const [showServerSelector, setShowServerSelector] = useState(false) - const [showParameterSchema, setShowParameterSchema] = useState(false) - // Track custom descriptions for each parameter const [parameterDescriptions, setParameterDescriptions] = useState>({}) const parameterSchema = useMemo( @@ -481,16 +251,13 @@ export function McpToolDeploy({ [inputFormat, parameterDescriptions] ) - // Track tools data from each server using state instead of hooks in a loop const [serverToolsMap, setServerToolsMap] = useState< Record >({}) - // Stable callback to handle tool data from ServerToolsQuery components const handleServerToolData = useCallback( (serverId: string, tool: WorkflowMcpTool | null, isLoading: boolean) => { setServerToolsMap((prev) => { - // Only update if data has changed to prevent infinite loops const existing = prev[serverId] if (existing?.tool?.id === tool?.id && existing?.isLoading === isLoading) { return prev @@ -504,114 +271,116 @@ export function McpToolDeploy({ [] ) - // Find which servers already have this workflow as a tool and get the tool info - const serversWithThisWorkflow = useMemo(() => { - const result: Array<{ server: WorkflowMcpServer; tool: WorkflowMcpTool }> = [] + const selectedServerIds = useMemo(() => { + const ids = new Set() for (const server of servers) { const toolInfo = serverToolsMap[server.id] if (toolInfo?.tool) { - result.push({ server, tool: toolInfo.tool }) + ids.add(server.id) } } - return result + return ids }, [servers, serverToolsMap]) - // Check if any tools need updating - const toolsNeedingUpdate = useMemo(() => { - return serversWithThisWorkflow.filter(({ tool }) => hasParameterMismatch(tool, inputFormat)) - }, [serversWithThisWorkflow, inputFormat]) - - // Load existing parameter descriptions from the first deployed tool + // Load existing tool name, description, and parameter descriptions from the first deployed tool useEffect(() => { - if (serversWithThisWorkflow.length > 0) { - const existingTool = serversWithThisWorkflow[0].tool - const schema = existingTool.parameterSchema as Record | undefined - const properties = schema?.properties as Record | undefined - - if (properties) { - const descriptions: Record = {} - for (const [name, prop] of Object.entries(properties)) { - // Only use description if it differs from the field name (i.e., it's custom) - if ( - prop.description && - prop.description !== name && - prop.description !== 'Array of file objects' - ) { - descriptions[name] = prop.description + for (const server of servers) { + const toolInfo = serverToolsMap[server.id] + if (toolInfo?.tool) { + setToolName(toolInfo.tool.toolName) + setToolDescription(toolInfo.tool.toolDescription || '') + + // Load parameter descriptions + const schema = toolInfo.tool.parameterSchema as Record | undefined + const properties = schema?.properties as + | Record + | undefined + if (properties) { + const descriptions: Record = {} + for (const [name, prop] of Object.entries(properties)) { + if ( + prop.description && + prop.description !== name && + prop.description !== 'Array of file objects' + ) { + descriptions[name] = prop.description + } + } + if (Object.keys(descriptions).length > 0) { + setParameterDescriptions(descriptions) } } - if (Object.keys(descriptions).length > 0) { - setParameterDescriptions(descriptions) - } + break } } - }, [serversWithThisWorkflow]) - - // Reset form when selected server changes - useEffect(() => { - if (selectedServer) { - setToolName(sanitizeToolName(workflowName)) - setToolDescription(workflowDescription || `Execute ${workflowName} workflow`) - } - }, [selectedServer, workflowName, workflowDescription]) - - const handleAddTool = useCallback(async () => { - if (!selectedServer || !toolName.trim()) return - - try { - await addToolMutation.mutateAsync({ - workspaceId, - serverId: selectedServer.id, - workflowId, - toolName: toolName.trim(), - toolDescription: toolDescription.trim() || undefined, - parameterSchema, - }) - - setSelectedServer(null) - setToolName('') - setToolDescription('') - - // Refetch servers to update tool count - refetchServers() - onAddedToServer?.() + }, [servers, serverToolsMap]) - logger.info(`Added workflow ${workflowId} as tool to server ${selectedServer.id}`) - } catch (error) { - logger.error('Failed to add tool:', error) - } - }, [ - selectedServer, - toolName, - toolDescription, - workspaceId, - workflowId, - parameterSchema, - addToolMutation, - refetchServers, - onAddedToServer, - ]) - - const handleToolChanged = useCallback( - (removedServerId?: string) => { - // If a tool was removed from a specific server, clear just that entry - // The ServerToolsQuery component will re-query and update the map - if (removedServerId) { - setServerToolsMap((prev) => { - const next = { ...prev } - delete next[removedServerId] - return next - }) + const handleServerToggle = useCallback( + async (server: WorkflowMcpServer) => { + const toolInfo = serverToolsMap[server.id] + const isSelected = !!toolInfo?.tool + + if (isSelected && toolInfo?.tool) { + // Remove from server + try { + await deleteToolMutation.mutateAsync({ + workspaceId, + serverId: server.id, + toolId: toolInfo.tool.id, + }) + setServerToolsMap((prev) => { + const next = { ...prev } + delete next[server.id] + return next + }) + refetchServers() + } catch (error) { + logger.error('Failed to remove tool:', error) + } + } else { + // Add to server + if (!toolName.trim()) return + try { + await addToolMutation.mutateAsync({ + workspaceId, + serverId: server.id, + workflowId, + toolName: toolName.trim(), + toolDescription: toolDescription.trim() || undefined, + parameterSchema, + }) + refetchServers() + onAddedToServer?.() + logger.info(`Added workflow ${workflowId} as tool to server ${server.id}`) + } catch (error) { + logger.error('Failed to add tool:', error) + } } - refetchServers() }, - [refetchServers] + [ + serverToolsMap, + toolName, + toolDescription, + workspaceId, + workflowId, + parameterSchema, + addToolMutation, + deleteToolMutation, + refetchServers, + onAddedToServer, + ] ) - const availableServers = useMemo(() => { - const addedServerIds = new Set(serversWithThisWorkflow.map((s) => s.server.id)) - return servers.filter((server) => !addedServerIds.has(server.id)) - }, [servers, serversWithThisWorkflow]) + const selectedServersText = useMemo(() => { + const count = selectedServerIds.size + if (count === 0) return 'Select servers' + if (count === 1) { + const serverId = Array.from(selectedServerIds)[0] + const server = servers.find((s) => s.id === serverId) + return server?.name || '1 server' + } + return `${count} servers` + }, [selectedServerIds, servers]) if (!isDeployed) { return ( @@ -629,9 +398,21 @@ export function McpToolDeploy({ if (isLoadingServers) { return ( -
- - +
+
+
+ + +
+
+ + +
+
+ + +
+
) } @@ -643,7 +424,7 @@ export function McpToolDeploy({

No MCP servers yet

- Create a Workflow MCP Server in Settings → Workflow MCP Servers first. + Create an MCP Server in Settings → MCP Servers first.

@@ -651,8 +432,8 @@ export function McpToolDeploy({ } return ( -
- {/* Query tools for each server using separate components to follow Rules of Hooks */} +
+ {/* Query tools for each server */} {servers.map((server) => ( ))} -
-

- Add this workflow as an MCP tool to make it callable by external MCP clients like Cursor - or Claude Desktop. -

-
- - {/* Update Warning */} - {toolsNeedingUpdate.length > 0 && ( -
- -

- {toolsNeedingUpdate.length} server{toolsNeedingUpdate.length > 1 ? 's have' : ' has'}{' '} - outdated tool definitions. Click "Update" on each to sync with current parameters. +

+ {/* Tool Name */} +
+ + setToolName(e.target.value)} + placeholder='e.g., book_flight' + /> +

+ Use lowercase letters, numbers, and underscores only

- )} - {/* Parameter Schema Preview */} -
- - - {showParameterSchema && ( -
- {inputFormat.length === 0 ? ( -

- No parameters defined. Add input fields in the Starter block to define tool - parameters. -

- ) : ( -
- {inputFormat.map((field, index) => ( -
-
- - {field.name} - - - {field.type} - -
- - setParameterDescriptions((prev) => ({ - ...prev, - [field.name]: e.target.value, - })) - } - placeholder={`Describe what "${field.name}" is for...`} - className='h-[32px] text-[12px]' - /> +