diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/file-viewer.tsx b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/file-viewer.tsx index c0503e5c4d..a8a529d169 100644 --- a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/file-viewer.tsx +++ b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/file-viewer.tsx @@ -255,7 +255,26 @@ function TextEditor({ ? fetchedContent : `${fetchedContent}\n${streamingContent}` // #region agent log - fetch('http://127.0.0.1:7774/ingest/b056eec6-a1ee-457f-8556-85f94314ca06',{method:'POST',headers:{'Content-Type':'application/json','X-Debug-Session-Id':'6f10b0'},body:JSON.stringify({sessionId:'6f10b0',location:'file-viewer.tsx:TextEditor-merge',message:'streaming merge',data:{streamingMode,fetchedContentLen:fetchedContent?.length,streamingContentLen:streamingContent.length,nextContentLen:nextContent.length,fetchedUndefined:fetchedContent===undefined,usedReplace:streamingMode==='replace'||fetchedContent===undefined,nextPreview:nextContent.slice(0,200)},timestamp:Date.now(),hypothesisId:'H2-H3'})}).catch(()=>{}); + fetch('http://127.0.0.1:7774/ingest/b056eec6-a1ee-457f-8556-85f94314ca06', { + method: 'POST', + headers: { 'Content-Type': 'application/json', 'X-Debug-Session-Id': '6f10b0' }, + body: JSON.stringify({ + sessionId: '6f10b0', + location: 'file-viewer.tsx:TextEditor-merge', + message: 'streaming merge', + data: { + streamingMode, + fetchedContentLen: fetchedContent?.length, + streamingContentLen: streamingContent.length, + nextContentLen: nextContent.length, + fetchedUndefined: fetchedContent === undefined, + usedReplace: streamingMode === 'replace' || fetchedContent === undefined, + nextPreview: nextContent.slice(0, 200), + }, + timestamp: Date.now(), + hypothesisId: 'H2-H3', + }), + }).catch(() => {}) // #endregion setContent(nextContent) contentRef.current = nextContent @@ -264,8 +283,8 @@ function TextEditor({ } if (wasStreamingRef.current) { - wasStreamingRef.current = false - if (fetchedContent !== undefined) { + if (fetchedContent !== undefined && fetchedContent !== savedContentRef.current) { + wasStreamingRef.current = false setContent(fetchedContent) setSavedContent(fetchedContent) savedContentRef.current = fetchedContent @@ -377,7 +396,8 @@ function TextEditor({ ) const isStreaming = streamingContent !== undefined - const revealedContent = useStreamingText(content, isStreaming) + const shouldAnimateStreaming = isStreaming && streamingMode === 'append' + const revealedContent = useStreamingText(content, shouldAnimateStreaming) const textareaStuckRef = useRef(true) diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-content/resource-content.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-content/resource-content.tsx index 1d01af58eb..987208cdf2 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-content/resource-content.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-content/resource-content.tsx @@ -122,7 +122,30 @@ export const ResourceContent = memo(function ResourceContent({ // #region agent log if (streamingFile) { - fetch('http://127.0.0.1:7774/ingest/b056eec6-a1ee-457f-8556-85f94314ca06',{method:'POST',headers:{'Content-Type':'application/json','X-Debug-Session-Id':'6f10b0'},body:JSON.stringify({sessionId:'6f10b0',location:'resource-content.tsx:streaming-context',message:'streaming state',data:{resourceId:resource.id,resourceType:resource.type,streamOp:streamOperation,isPatch:isPatchStream,isWrite:isWriteStream,isUpdate:isUpdateStream,hasActiveFileRecord:!!activeFileRecord,hasFetchedContent:!!fetchedFileContent,fetchedContentLen:fetchedFileContent?.length,streamingFileContentLen:streamingFile.content.length,streamingFileName:streamingFile.fileName,streamingFileMode:isWriteStream?'append':'replace'},timestamp:Date.now()})}).catch(()=>{}); + fetch('http://127.0.0.1:7774/ingest/b056eec6-a1ee-457f-8556-85f94314ca06', { + method: 'POST', + headers: { 'Content-Type': 'application/json', 'X-Debug-Session-Id': '6f10b0' }, + body: JSON.stringify({ + sessionId: '6f10b0', + location: 'resource-content.tsx:streaming-context', + message: 'streaming state', + data: { + resourceId: resource.id, + resourceType: resource.type, + streamOp: streamOperation, + isPatch: isPatchStream, + isWrite: isWriteStream, + isUpdate: isUpdateStream, + hasActiveFileRecord: !!activeFileRecord, + hasFetchedContent: !!fetchedFileContent, + fetchedContentLen: fetchedFileContent?.length, + streamingFileContentLen: streamingFile.content.length, + streamingFileName: streamingFile.fileName, + streamingFileMode: isWriteStream ? 'append' : 'replace', + }, + timestamp: Date.now(), + }), + }).catch(() => {}) } // #endregion const streamingExtractedContent = useMemo(() => { @@ -132,13 +155,41 @@ export const ResourceContent = memo(function ResourceContent({ if (isPatchStream) { if (!fetchedFileContent) { // #region agent log - fetch('http://127.0.0.1:7774/ingest/b056eec6-a1ee-457f-8556-85f94314ca06',{method:'POST',headers:{'Content-Type':'application/json','X-Debug-Session-Id':'6f10b0'},body:JSON.stringify({sessionId:'6f10b0',location:'resource-content.tsx:patch-no-fetched',message:'patch but no fetchedFileContent',data:{resourceId:resource.id,activeFileRecordId:activeFileRecord?.id},timestamp:Date.now(),hypothesisId:'H1'})}).catch(()=>{}); + fetch('http://127.0.0.1:7774/ingest/b056eec6-a1ee-457f-8556-85f94314ca06', { + method: 'POST', + headers: { 'Content-Type': 'application/json', 'X-Debug-Session-Id': '6f10b0' }, + body: JSON.stringify({ + sessionId: '6f10b0', + location: 'resource-content.tsx:patch-no-fetched', + message: 'patch but no fetchedFileContent', + data: { resourceId: resource.id, activeFileRecordId: activeFileRecord?.id }, + timestamp: Date.now(), + hypothesisId: 'H1', + }), + }).catch(() => {}) // #endregion return undefined } const patchResult = extractPatchPreview(streamingFile, fetchedFileContent) // #region agent log - fetch('http://127.0.0.1:7774/ingest/b056eec6-a1ee-457f-8556-85f94314ca06',{method:'POST',headers:{'Content-Type':'application/json','X-Debug-Session-Id':'6f10b0'},body:JSON.stringify({sessionId:'6f10b0',location:'resource-content.tsx:patch-result',message:'extractPatchPreview result',data:{hasPatchResult:!!patchResult,patchResultLen:patchResult?.length,fetchedLen:fetchedFileContent.length,contentPreview:streamingFile.content.slice(0,200),edit:streamingFile.edit},timestamp:Date.now(),hypothesisId:'H4'})}).catch(()=>{}); + fetch('http://127.0.0.1:7774/ingest/b056eec6-a1ee-457f-8556-85f94314ca06', { + method: 'POST', + headers: { 'Content-Type': 'application/json', 'X-Debug-Session-Id': '6f10b0' }, + body: JSON.stringify({ + sessionId: '6f10b0', + location: 'resource-content.tsx:patch-result', + message: 'extractPatchPreview result', + data: { + hasPatchResult: !!patchResult, + patchResultLen: patchResult?.length, + fetchedLen: fetchedFileContent.length, + contentPreview: streamingFile.content.slice(0, 200), + edit: streamingFile.edit, + }, + timestamp: Date.now(), + hypothesisId: 'H4', + }), + }).catch(() => {}) // #endregion return patchResult } @@ -147,14 +198,36 @@ export const ResourceContent = memo(function ResourceContent({ if (extracted.length === 0) return undefined // #region agent log - fetch('http://127.0.0.1:7774/ingest/b056eec6-a1ee-457f-8556-85f94314ca06',{method:'POST',headers:{'Content-Type':'application/json','X-Debug-Session-Id':'6f10b0'},body:JSON.stringify({sessionId:'6f10b0',location:'resource-content.tsx:write-update-content',message:'extracted content for write/update',data:{streamOp:streamOperation,extractedLen:extracted.length,extractedPreview:extracted.slice(0,150)},timestamp:Date.now(),hypothesisId:'H2'})}).catch(()=>{}); + fetch('http://127.0.0.1:7774/ingest/b056eec6-a1ee-457f-8556-85f94314ca06', { + method: 'POST', + headers: { 'Content-Type': 'application/json', 'X-Debug-Session-Id': '6f10b0' }, + body: JSON.stringify({ + sessionId: '6f10b0', + location: 'resource-content.tsx:write-update-content', + message: 'extracted content for write/update', + data: { + streamOp: streamOperation, + extractedLen: extracted.length, + extractedPreview: extracted.slice(0, 150), + }, + timestamp: Date.now(), + hypothesisId: 'H2', + }), + }).catch(() => {}) // #endregion if (isUpdateStream) return extracted if (isWriteStream) return extracted return undefined - }, [streamingFile, streamOperation, isWriteStream, isPatchStream, isUpdateStream, fetchedFileContent]) + }, [ + streamingFile, + streamOperation, + isWriteStream, + isPatchStream, + isUpdateStream, + fetchedFileContent, + ]) const syntheticFile = useMemo(() => { const ext = getFileExtension(streamFileName) const SOURCE_MIME_MAP: Record = { @@ -176,17 +249,14 @@ export const ResourceContent = memo(function ResourceContent({ } }, [workspaceId, streamFileName]) - const streamingFileMode: 'append' | 'replace' = - isWriteStream ? 'append' : 'replace' + const streamingFileMode: 'append' | 'replace' = isWriteStream ? 'append' : 'replace' // For existing file resources (not streaming-file), only pass streaming // content for patch operations where the preview splices new content into // the displayed file. Update operations re-stream the entire file from // scratch which causes visual duplication of already-visible content. const embeddedStreamingContent = - resource.id !== 'streaming-file' && isUpdateStream - ? undefined - : streamingExtractedContent + resource.id !== 'streaming-file' && isUpdateStream ? undefined : streamingExtractedContent if (streamingFile && resource.id === 'streaming-file') { return ( @@ -513,7 +583,13 @@ interface EmbeddedFileProps { streamingMode?: 'append' | 'replace' } -function EmbeddedFile({ workspaceId, fileId, previewMode, streamingContent, streamingMode }: EmbeddedFileProps) { +function EmbeddedFile({ + workspaceId, + fileId, + previewMode, + streamingContent, + streamingMode, +}: EmbeddedFileProps) { const { canEdit } = useUserPermissionsContext() const { data: files = [], isLoading, isFetching } = useWorkspaceFiles(workspaceId) const file = useMemo(() => files.find((f) => f.id === fileId), [files, fileId]) @@ -638,9 +714,7 @@ function extractPatchPreview( const strategy = typeof edit.strategy === 'string' ? edit.strategy : undefined const lines = existingContent.split('\n') const occurrence = - typeof edit.occurrence === 'number' && Number.isFinite(edit.occurrence) - ? edit.occurrence - : 1 + typeof edit.occurrence === 'number' && Number.isFinite(edit.occurrence) ? edit.occurrence : 1 if (strategy === 'search_replace') { const search = typeof edit.search === 'string' ? edit.search : '' @@ -651,7 +725,9 @@ function extractPatchPreview( } const firstIdx = existingContent.indexOf(search) if (firstIdx === -1) return undefined - return existingContent.slice(0, firstIdx) + replace + existingContent.slice(firstIdx + search.length) + return ( + existingContent.slice(0, firstIdx) + replace + existingContent.slice(firstIdx + search.length) + ) } const mode = typeof edit.mode === 'string' ? edit.mode : undefined diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-tabs/resource-tabs.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-tabs/resource-tabs.tsx index d8956b1336..576054d08e 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-tabs/resource-tabs.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-tabs/resource-tabs.tsx @@ -9,8 +9,8 @@ import { } from 'react' import { Button, Tooltip } from '@/components/emcn' import { Columns3, Eye, PanelLeft, Pencil } from '@/components/emcn/icons' -import { isEphemeralResource } from '@/lib/copilot/resources/types' import { SIM_RESOURCE_DRAG_TYPE } from '@/lib/copilot/resource-types' +import { isEphemeralResource } from '@/lib/copilot/resources/types' import { cn } from '@/lib/core/utils/cn' import type { PreviewMode } from '@/app/workspace/[workspaceId]/files/components/file-viewer' import { AddResourceDropdown } from '@/app/workspace/[workspaceId]/home/components/mothership-view/components/add-resource-dropdown' diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/mothership-view.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/mothership-view.tsx index fb5c1c44d3..ad85354ac5 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/mothership-view.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/mothership-view.tsx @@ -58,17 +58,15 @@ interface MothershipViewProps { onCollapse: () => void isCollapsed: boolean className?: string - streamingFile?: - | { - toolCallId?: string - fileName: string - fileId?: string - targetKind?: 'new_file' | 'file_id' - operation?: string - edit?: Record - content: string - } - | null + streamingFile?: { + toolCallId?: string + fileName: string + fileId?: string + targetKind?: 'new_file' | 'file_id' + operation?: string + edit?: Record + content: string + } | null genericResourceData?: GenericResourceData } diff --git a/apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts b/apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts index d57f57d703..159620c074 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts +++ b/apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts @@ -904,13 +904,15 @@ export function useChat( const target = asPayloadRecord(payload.target) const nextSession: StreamingFilePreview = { ...prevSession, - operation: typeof payload.operation === 'string' ? payload.operation : prevSession.operation, + operation: + typeof payload.operation === 'string' + ? payload.operation + : prevSession.operation, targetKind: target?.kind === 'new_file' || target?.kind === 'file_id' ? (target.kind as 'new_file' | 'file_id') : prevSession.targetKind, - fileId: - typeof target?.fileId === 'string' ? target.fileId : prevSession.fileId, + fileId: typeof target?.fileId === 'string' ? target.fileId : prevSession.fileId, fileName: typeof target?.fileName === 'string' ? target.fileName : prevSession.fileName, } @@ -954,13 +956,11 @@ export function useChat( break } - if (previewPhase === 'file_preview_content_delta') { - const delta = - typeof payload.delta === 'string' ? payload.delta : '' - if (!delta) break + if (previewPhase === 'file_preview_content') { + const content = typeof payload.content === 'string' ? payload.content : '' const nextSession: StreamingFilePreview = { ...prevSession, - content: (prevSession.content ?? '') + delta, + content, } sessions.set(id, nextSession) activeFilePreviewToolCallIdRef.current = id diff --git a/apps/sim/lib/copilot/generated/tool-catalog-v1.ts b/apps/sim/lib/copilot/generated/tool-catalog-v1.ts index b8ecf0188f..d2e503552f 100644 --- a/apps/sim/lib/copilot/generated/tool-catalog-v1.ts +++ b/apps/sim/lib/copilot/generated/tool-catalog-v1.ts @@ -3,753 +3,2621 @@ // export interface ToolCatalogEntry { - clientExecutable?: boolean; - executor: "client" | "go" | "sim" | "subagent"; - hidden?: boolean; - id: "agent" | "auth" | "check_deployment_status" | "complete_job" | "context_write" | "crawl_website" | "create_folder" | "create_job" | "create_workflow" | "create_workspace_mcp_server" | "debug" | "delete_folder" | "delete_workflow" | "delete_workspace_mcp_server" | "deploy" | "deploy_api" | "deploy_chat" | "deploy_mcp" | "download_to_workspace_file" | "edit_workflow" | "file" | "function_execute" | "generate_api_key" | "generate_image" | "generate_visualization" | "get_block_outputs" | "get_block_upstream_references" | "get_deployed_workflow_state" | "get_deployment_version" | "get_execution_summary" | "get_job_logs" | "get_page_contents" | "get_platform_actions" | "get_workflow_data" | "get_workflow_logs" | "glob" | "grep" | "job" | "knowledge" | "knowledge_base" | "list_folders" | "list_user_workspaces" | "list_workspace_mcp_servers" | "manage_credential" | "manage_custom_tool" | "manage_job" | "manage_mcp_tool" | "manage_skill" | "materialize_file" | "move_folder" | "move_workflow" | "oauth_get_auth_link" | "oauth_request_access" | "open_resource" | "read" | "redeploy" | "rename_workflow" | "research" | "respond" | "revert_to_version" | "run" | "run_block" | "run_from_block" | "run_workflow" | "run_workflow_until_block" | "scrape_page" | "search_documentation" | "search_library_docs" | "search_online" | "search_patterns" | "set_environment_variables" | "set_global_workflow_variables" | "superagent" | "table" | "tool_search_tool_regex" | "update_job_history" | "update_workspace_mcp_server" | "user_memory" | "user_table" | "workflow" | "workspace_file"; - internal?: boolean; - mode: "async" | "sync"; - name: "agent" | "auth" | "check_deployment_status" | "complete_job" | "context_write" | "crawl_website" | "create_folder" | "create_job" | "create_workflow" | "create_workspace_mcp_server" | "debug" | "delete_folder" | "delete_workflow" | "delete_workspace_mcp_server" | "deploy" | "deploy_api" | "deploy_chat" | "deploy_mcp" | "download_to_workspace_file" | "edit_workflow" | "file" | "function_execute" | "generate_api_key" | "generate_image" | "generate_visualization" | "get_block_outputs" | "get_block_upstream_references" | "get_deployed_workflow_state" | "get_deployment_version" | "get_execution_summary" | "get_job_logs" | "get_page_contents" | "get_platform_actions" | "get_workflow_data" | "get_workflow_logs" | "glob" | "grep" | "job" | "knowledge" | "knowledge_base" | "list_folders" | "list_user_workspaces" | "list_workspace_mcp_servers" | "manage_credential" | "manage_custom_tool" | "manage_job" | "manage_mcp_tool" | "manage_skill" | "materialize_file" | "move_folder" | "move_workflow" | "oauth_get_auth_link" | "oauth_request_access" | "open_resource" | "read" | "redeploy" | "rename_workflow" | "research" | "respond" | "revert_to_version" | "run" | "run_block" | "run_from_block" | "run_workflow" | "run_workflow_until_block" | "scrape_page" | "search_documentation" | "search_library_docs" | "search_online" | "search_patterns" | "set_environment_variables" | "set_global_workflow_variables" | "superagent" | "table" | "tool_search_tool_regex" | "update_job_history" | "update_workspace_mcp_server" | "user_memory" | "user_table" | "workflow" | "workspace_file"; - parameters: unknown; - requiredPermission?: "admin" | "write"; - requiresConfirmation?: boolean; - resultSchema?: unknown; - subagentId?: "agent" | "auth" | "debug" | "deploy" | "file" | "job" | "knowledge" | "research" | "run" | "superagent" | "table" | "workflow"; + clientExecutable?: boolean + executor: 'client' | 'go' | 'sim' | 'subagent' + hidden?: boolean + id: + | 'agent' + | 'auth' + | 'check_deployment_status' + | 'complete_job' + | 'context_write' + | 'crawl_website' + | 'create_folder' + | 'create_job' + | 'create_workflow' + | 'create_workspace_mcp_server' + | 'debug' + | 'delete_folder' + | 'delete_workflow' + | 'delete_workspace_mcp_server' + | 'deploy' + | 'deploy_api' + | 'deploy_chat' + | 'deploy_mcp' + | 'download_to_workspace_file' + | 'edit_workflow' + | 'file' + | 'function_execute' + | 'generate_api_key' + | 'generate_image' + | 'generate_visualization' + | 'get_block_outputs' + | 'get_block_upstream_references' + | 'get_deployed_workflow_state' + | 'get_deployment_version' + | 'get_execution_summary' + | 'get_job_logs' + | 'get_page_contents' + | 'get_platform_actions' + | 'get_workflow_data' + | 'get_workflow_logs' + | 'glob' + | 'grep' + | 'job' + | 'knowledge' + | 'knowledge_base' + | 'list_folders' + | 'list_user_workspaces' + | 'list_workspace_mcp_servers' + | 'manage_credential' + | 'manage_custom_tool' + | 'manage_job' + | 'manage_mcp_tool' + | 'manage_skill' + | 'materialize_file' + | 'move_folder' + | 'move_workflow' + | 'oauth_get_auth_link' + | 'oauth_request_access' + | 'open_resource' + | 'read' + | 'redeploy' + | 'rename_workflow' + | 'research' + | 'respond' + | 'revert_to_version' + | 'run' + | 'run_block' + | 'run_from_block' + | 'run_workflow' + | 'run_workflow_until_block' + | 'scrape_page' + | 'search_documentation' + | 'search_library_docs' + | 'search_online' + | 'search_patterns' + | 'set_environment_variables' + | 'set_global_workflow_variables' + | 'superagent' + | 'table' + | 'tool_search_tool_regex' + | 'update_job_history' + | 'update_workspace_mcp_server' + | 'user_memory' + | 'user_table' + | 'workflow' + | 'workspace_file' + internal?: boolean + mode: 'async' | 'sync' + name: + | 'agent' + | 'auth' + | 'check_deployment_status' + | 'complete_job' + | 'context_write' + | 'crawl_website' + | 'create_folder' + | 'create_job' + | 'create_workflow' + | 'create_workspace_mcp_server' + | 'debug' + | 'delete_folder' + | 'delete_workflow' + | 'delete_workspace_mcp_server' + | 'deploy' + | 'deploy_api' + | 'deploy_chat' + | 'deploy_mcp' + | 'download_to_workspace_file' + | 'edit_workflow' + | 'file' + | 'function_execute' + | 'generate_api_key' + | 'generate_image' + | 'generate_visualization' + | 'get_block_outputs' + | 'get_block_upstream_references' + | 'get_deployed_workflow_state' + | 'get_deployment_version' + | 'get_execution_summary' + | 'get_job_logs' + | 'get_page_contents' + | 'get_platform_actions' + | 'get_workflow_data' + | 'get_workflow_logs' + | 'glob' + | 'grep' + | 'job' + | 'knowledge' + | 'knowledge_base' + | 'list_folders' + | 'list_user_workspaces' + | 'list_workspace_mcp_servers' + | 'manage_credential' + | 'manage_custom_tool' + | 'manage_job' + | 'manage_mcp_tool' + | 'manage_skill' + | 'materialize_file' + | 'move_folder' + | 'move_workflow' + | 'oauth_get_auth_link' + | 'oauth_request_access' + | 'open_resource' + | 'read' + | 'redeploy' + | 'rename_workflow' + | 'research' + | 'respond' + | 'revert_to_version' + | 'run' + | 'run_block' + | 'run_from_block' + | 'run_workflow' + | 'run_workflow_until_block' + | 'scrape_page' + | 'search_documentation' + | 'search_library_docs' + | 'search_online' + | 'search_patterns' + | 'set_environment_variables' + | 'set_global_workflow_variables' + | 'superagent' + | 'table' + | 'tool_search_tool_regex' + | 'update_job_history' + | 'update_workspace_mcp_server' + | 'user_memory' + | 'user_table' + | 'workflow' + | 'workspace_file' + parameters: unknown + requiredPermission?: 'admin' | 'write' + requiresConfirmation?: boolean + resultSchema?: unknown + subagentId?: + | 'agent' + | 'auth' + | 'debug' + | 'deploy' + | 'file' + | 'job' + | 'knowledge' + | 'research' + | 'run' + | 'superagent' + | 'table' + | 'workflow' } export const Agent: ToolCatalogEntry = { - id: "agent", - name: "agent", - executor: "subagent", - mode: "async", - parameters: {"properties":{"request":{"description":"What tool/skill/MCP action is needed.","type":"string"}},"required":["request"],"type":"object"}, - subagentId: "agent", + id: 'agent', + name: 'agent', + executor: 'subagent', + mode: 'async', + parameters: { + properties: { + request: { description: 'What tool/skill/MCP action is needed.', type: 'string' }, + }, + required: ['request'], + type: 'object', + }, + subagentId: 'agent', internal: true, - requiredPermission: "write", -}; + requiredPermission: 'write', +} export const Auth: ToolCatalogEntry = { - id: "auth", - name: "auth", - executor: "subagent", - mode: "async", - parameters: {"properties":{"request":{"description":"What authentication/credential action is needed.","type":"string"}},"required":["request"],"type":"object"}, - subagentId: "auth", + id: 'auth', + name: 'auth', + executor: 'subagent', + mode: 'async', + parameters: { + properties: { + request: { description: 'What authentication/credential action is needed.', type: 'string' }, + }, + required: ['request'], + type: 'object', + }, + subagentId: 'auth', internal: true, -}; +} export const CheckDeploymentStatus: ToolCatalogEntry = { - id: "check_deployment_status", - name: "check_deployment_status", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"workflowId":{"type":"string","description":"Workflow ID to check (defaults to current workflow)"}}}, -}; + id: 'check_deployment_status', + name: 'check_deployment_status', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + workflowId: { + type: 'string', + description: 'Workflow ID to check (defaults to current workflow)', + }, + }, + }, +} export const CompleteJob: ToolCatalogEntry = { - id: "complete_job", - name: "complete_job", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"jobId":{"type":"string","description":"The ID of the job to mark as completed."}},"required":["jobId"]}, -}; + id: 'complete_job', + name: 'complete_job', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + jobId: { type: 'string', description: 'The ID of the job to mark as completed.' }, + }, + required: ['jobId'], + }, +} export const ContextWrite: ToolCatalogEntry = { - id: "context_write", - name: "context_write", - executor: "go", - mode: "sync", - parameters: {"type":"object","properties":{"content":{"type":"string","description":"Full content to write to the file (replaces existing content)"},"file_path":{"type":"string","description":"Path of the file to write (e.g. 'SESSION.md')"}},"required":["file_path","content"]}, -}; + id: 'context_write', + name: 'context_write', + executor: 'go', + mode: 'sync', + parameters: { + type: 'object', + properties: { + content: { + type: 'string', + description: 'Full content to write to the file (replaces existing content)', + }, + file_path: { type: 'string', description: "Path of the file to write (e.g. 'SESSION.md')" }, + }, + required: ['file_path', 'content'], + }, +} export const CrawlWebsite: ToolCatalogEntry = { - id: "crawl_website", - name: "crawl_website", - executor: "go", - mode: "sync", - parameters: {"type":"object","properties":{"exclude_paths":{"type":"array","description":"Skip URLs matching these patterns","items":{"type":"string"}},"include_paths":{"type":"array","description":"Only crawl URLs matching these patterns","items":{"type":"string"}},"limit":{"type":"number","description":"Maximum pages to crawl (default 10, max 50)"},"max_depth":{"type":"number","description":"How deep to follow links (default 2)"},"url":{"type":"string","description":"Starting URL to crawl from"}},"required":["url"]}, -}; + id: 'crawl_website', + name: 'crawl_website', + executor: 'go', + mode: 'sync', + parameters: { + type: 'object', + properties: { + exclude_paths: { + type: 'array', + description: 'Skip URLs matching these patterns', + items: { type: 'string' }, + }, + include_paths: { + type: 'array', + description: 'Only crawl URLs matching these patterns', + items: { type: 'string' }, + }, + limit: { type: 'number', description: 'Maximum pages to crawl (default 10, max 50)' }, + max_depth: { type: 'number', description: 'How deep to follow links (default 2)' }, + url: { type: 'string', description: 'Starting URL to crawl from' }, + }, + required: ['url'], + }, +} export const CreateFolder: ToolCatalogEntry = { - id: "create_folder", - name: "create_folder", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"name":{"type":"string","description":"Folder name."},"parentId":{"type":"string","description":"Optional parent folder ID."},"workspaceId":{"type":"string","description":"Optional workspace ID."}},"required":["name"]}, - requiredPermission: "write", -}; + id: 'create_folder', + name: 'create_folder', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + name: { type: 'string', description: 'Folder name.' }, + parentId: { type: 'string', description: 'Optional parent folder ID.' }, + workspaceId: { type: 'string', description: 'Optional workspace ID.' }, + }, + required: ['name'], + }, + requiredPermission: 'write', +} export const CreateJob: ToolCatalogEntry = { - id: "create_job", - name: "create_job", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"cron":{"type":"string","description":"Cron expression for recurring jobs (e.g., '*/5 * * * *' for every 5 minutes, '0 9 * * *' for daily at 9 AM). Omit for one-time jobs."},"lifecycle":{"type":"string","description":"'persistent' (default) or 'until_complete'. Until_complete jobs stop when complete_job is called after the success condition is met.","enum":["persistent","until_complete"]},"maxRuns":{"type":"integer","description":"Maximum number of executions before the job auto-completes. Safety limit to prevent runaway polling."},"prompt":{"type":"string","description":"The prompt to execute when the job fires. This is sent to the Mothership as a user message."},"successCondition":{"type":"string","description":"What must happen for the job to be considered complete. Used with until_complete lifecycle (e.g., 'John has replied to the partnership email')."},"time":{"type":"string","description":"ISO 8601 datetime for one-time execution or as the start time for a cron schedule (e.g., '2026-03-06T09:00:00'). Include timezone offset or use the timezone parameter."},"timezone":{"type":"string","description":"IANA timezone for the schedule (e.g., 'America/New_York', 'Europe/London'). Defaults to UTC."},"title":{"type":"string","description":"A short, descriptive title for the job (e.g., 'Email Poller', 'Daily Report'). Used as the display name."}},"required":["title","prompt"]}, -}; + id: 'create_job', + name: 'create_job', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + cron: { + type: 'string', + description: + "Cron expression for recurring jobs (e.g., '*/5 * * * *' for every 5 minutes, '0 9 * * *' for daily at 9 AM). Omit for one-time jobs.", + }, + lifecycle: { + type: 'string', + description: + "'persistent' (default) or 'until_complete'. Until_complete jobs stop when complete_job is called after the success condition is met.", + enum: ['persistent', 'until_complete'], + }, + maxRuns: { + type: 'integer', + description: + 'Maximum number of executions before the job auto-completes. Safety limit to prevent runaway polling.', + }, + prompt: { + type: 'string', + description: + 'The prompt to execute when the job fires. This is sent to the Mothership as a user message.', + }, + successCondition: { + type: 'string', + description: + "What must happen for the job to be considered complete. Used with until_complete lifecycle (e.g., 'John has replied to the partnership email').", + }, + time: { + type: 'string', + description: + "ISO 8601 datetime for one-time execution or as the start time for a cron schedule (e.g., '2026-03-06T09:00:00'). Include timezone offset or use the timezone parameter.", + }, + timezone: { + type: 'string', + description: + "IANA timezone for the schedule (e.g., 'America/New_York', 'Europe/London'). Defaults to UTC.", + }, + title: { + type: 'string', + description: + "A short, descriptive title for the job (e.g., 'Email Poller', 'Daily Report'). Used as the display name.", + }, + }, + required: ['title', 'prompt'], + }, +} export const CreateWorkflow: ToolCatalogEntry = { - id: "create_workflow", - name: "create_workflow", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"description":{"type":"string","description":"Optional workflow description."},"folderId":{"type":"string","description":"Optional folder ID."},"name":{"type":"string","description":"Workflow name."},"workspaceId":{"type":"string","description":"Optional workspace ID."}},"required":["name"]}, - requiredPermission: "write", -}; + id: 'create_workflow', + name: 'create_workflow', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + description: { type: 'string', description: 'Optional workflow description.' }, + folderId: { type: 'string', description: 'Optional folder ID.' }, + name: { type: 'string', description: 'Workflow name.' }, + workspaceId: { type: 'string', description: 'Optional workspace ID.' }, + }, + required: ['name'], + }, + requiredPermission: 'write', +} export const CreateWorkspaceMcpServer: ToolCatalogEntry = { - id: "create_workspace_mcp_server", - name: "create_workspace_mcp_server", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"description":{"type":"string","description":"Optional description for the server"},"name":{"type":"string","description":"Required: server name"},"workspaceId":{"type":"string","description":"Workspace ID (defaults to current workspace)"}},"required":["name"]}, + id: 'create_workspace_mcp_server', + name: 'create_workspace_mcp_server', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + description: { type: 'string', description: 'Optional description for the server' }, + name: { type: 'string', description: 'Required: server name' }, + workspaceId: { type: 'string', description: 'Workspace ID (defaults to current workspace)' }, + }, + required: ['name'], + }, requiresConfirmation: true, - requiredPermission: "admin", -}; + requiredPermission: 'admin', +} export const Debug: ToolCatalogEntry = { - id: "debug", - name: "debug", - executor: "subagent", - mode: "async", - parameters: {"properties":{"context":{"description":"Pre-gathered context: workflow state JSON, block schemas, error logs. The debug agent will skip re-reading anything included here.","type":"string"},"request":{"description":"What to debug. Include error messages, block IDs, and any context about the failure.","type":"string"}},"required":["request"],"type":"object"}, - subagentId: "debug", + id: 'debug', + name: 'debug', + executor: 'subagent', + mode: 'async', + parameters: { + properties: { + context: { + description: + 'Pre-gathered context: workflow state JSON, block schemas, error logs. The debug agent will skip re-reading anything included here.', + type: 'string', + }, + request: { + description: + 'What to debug. Include error messages, block IDs, and any context about the failure.', + type: 'string', + }, + }, + required: ['request'], + type: 'object', + }, + subagentId: 'debug', internal: true, -}; +} export const DeleteFolder: ToolCatalogEntry = { - id: "delete_folder", - name: "delete_folder", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"folderId":{"type":"string","description":"The folder ID to delete."}},"required":["folderId"]}, + id: 'delete_folder', + name: 'delete_folder', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { folderId: { type: 'string', description: 'The folder ID to delete.' } }, + required: ['folderId'], + }, requiresConfirmation: true, - requiredPermission: "write", -}; + requiredPermission: 'write', +} export const DeleteWorkflow: ToolCatalogEntry = { - id: "delete_workflow", - name: "delete_workflow", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"workflowId":{"type":"string","description":"The workflow ID to delete."}},"required":["workflowId"]}, + id: 'delete_workflow', + name: 'delete_workflow', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { workflowId: { type: 'string', description: 'The workflow ID to delete.' } }, + required: ['workflowId'], + }, requiresConfirmation: true, - requiredPermission: "write", -}; + requiredPermission: 'write', +} export const DeleteWorkspaceMcpServer: ToolCatalogEntry = { - id: "delete_workspace_mcp_server", - name: "delete_workspace_mcp_server", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"serverId":{"type":"string","description":"Required: the MCP server ID to delete"}},"required":["serverId"]}, + id: 'delete_workspace_mcp_server', + name: 'delete_workspace_mcp_server', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + serverId: { type: 'string', description: 'Required: the MCP server ID to delete' }, + }, + required: ['serverId'], + }, requiresConfirmation: true, - requiredPermission: "admin", -}; + requiredPermission: 'admin', +} export const Deploy: ToolCatalogEntry = { - id: "deploy", - name: "deploy", - executor: "subagent", - mode: "async", - parameters: {"properties":{"request":{"description":"Detailed deployment instructions. Include deployment type (api/chat) and ALL user-specified options: identifier, title, description, authType, password, allowedEmails, welcomeMessage, outputConfigs (block outputs to display).","type":"string"}},"required":["request"],"type":"object"}, - subagentId: "deploy", + id: 'deploy', + name: 'deploy', + executor: 'subagent', + mode: 'async', + parameters: { + properties: { + request: { + description: + 'Detailed deployment instructions. Include deployment type (api/chat) and ALL user-specified options: identifier, title, description, authType, password, allowedEmails, welcomeMessage, outputConfigs (block outputs to display).', + type: 'string', + }, + }, + required: ['request'], + type: 'object', + }, + subagentId: 'deploy', internal: true, -}; +} export const DeployApi: ToolCatalogEntry = { - id: "deploy_api", - name: "deploy_api", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"action":{"type":"string","description":"Whether to deploy or undeploy the API endpoint","enum":["deploy","undeploy"],"default":"deploy"},"workflowId":{"type":"string","description":"Workflow ID to deploy (required in workspace context)"}}}, + id: 'deploy_api', + name: 'deploy_api', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + action: { + type: 'string', + description: 'Whether to deploy or undeploy the API endpoint', + enum: ['deploy', 'undeploy'], + default: 'deploy', + }, + workflowId: { + type: 'string', + description: 'Workflow ID to deploy (required in workspace context)', + }, + }, + }, requiresConfirmation: true, - requiredPermission: "admin", -}; + requiredPermission: 'admin', +} export const DeployChat: ToolCatalogEntry = { - id: "deploy_chat", - name: "deploy_chat", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"action":{"type":"string","description":"Whether to deploy or undeploy the chat interface","enum":["deploy","undeploy"],"default":"deploy"},"allowedEmails":{"type":"array","description":"List of allowed emails/domains for email or SSO auth","items":{"type":"string"}},"authType":{"type":"string","description":"Authentication type: public, password, email, or sso","enum":["public","password","email","sso"],"default":"public"},"description":{"type":"string","description":"Optional description for the chat"},"identifier":{"type":"string","description":"URL slug for the chat (lowercase letters, numbers, hyphens only)"},"outputConfigs":{"type":"array","description":"Output configurations specifying which block outputs to display in chat","items":{"type":"object","properties":{"blockId":{"type":"string","description":"The block UUID"},"path":{"type":"string","description":"The output path (e.g. 'response', 'response.content')"}},"required":["blockId","path"]}},"password":{"type":"string","description":"Password for password-protected chats"},"title":{"type":"string","description":"Display title for the chat interface"},"welcomeMessage":{"type":"string","description":"Welcome message shown to users"},"workflowId":{"type":"string","description":"Workflow ID to deploy (required in workspace context)"}}}, + id: 'deploy_chat', + name: 'deploy_chat', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + action: { + type: 'string', + description: 'Whether to deploy or undeploy the chat interface', + enum: ['deploy', 'undeploy'], + default: 'deploy', + }, + allowedEmails: { + type: 'array', + description: 'List of allowed emails/domains for email or SSO auth', + items: { type: 'string' }, + }, + authType: { + type: 'string', + description: 'Authentication type: public, password, email, or sso', + enum: ['public', 'password', 'email', 'sso'], + default: 'public', + }, + description: { type: 'string', description: 'Optional description for the chat' }, + identifier: { + type: 'string', + description: 'URL slug for the chat (lowercase letters, numbers, hyphens only)', + }, + outputConfigs: { + type: 'array', + description: 'Output configurations specifying which block outputs to display in chat', + items: { + type: 'object', + properties: { + blockId: { type: 'string', description: 'The block UUID' }, + path: { + type: 'string', + description: "The output path (e.g. 'response', 'response.content')", + }, + }, + required: ['blockId', 'path'], + }, + }, + password: { type: 'string', description: 'Password for password-protected chats' }, + title: { type: 'string', description: 'Display title for the chat interface' }, + welcomeMessage: { type: 'string', description: 'Welcome message shown to users' }, + workflowId: { + type: 'string', + description: 'Workflow ID to deploy (required in workspace context)', + }, + }, + }, requiresConfirmation: true, - requiredPermission: "admin", -}; + requiredPermission: 'admin', +} export const DeployMcp: ToolCatalogEntry = { - id: "deploy_mcp", - name: "deploy_mcp", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"parameterDescriptions":{"type":"array","description":"Array of parameter descriptions for the tool","items":{"type":"object","properties":{"description":{"type":"string","description":"Parameter description"},"name":{"type":"string","description":"Parameter name"}},"required":["name","description"]}},"serverId":{"type":"string","description":"Required: server ID from list_workspace_mcp_servers"},"toolDescription":{"type":"string","description":"Description for the MCP tool"},"toolName":{"type":"string","description":"Name for the MCP tool (defaults to workflow name)"},"workflowId":{"type":"string","description":"Workflow ID (defaults to active workflow)"}},"required":["serverId"]}, + id: 'deploy_mcp', + name: 'deploy_mcp', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + parameterDescriptions: { + type: 'array', + description: 'Array of parameter descriptions for the tool', + items: { + type: 'object', + properties: { + description: { type: 'string', description: 'Parameter description' }, + name: { type: 'string', description: 'Parameter name' }, + }, + required: ['name', 'description'], + }, + }, + serverId: { + type: 'string', + description: 'Required: server ID from list_workspace_mcp_servers', + }, + toolDescription: { type: 'string', description: 'Description for the MCP tool' }, + toolName: { + type: 'string', + description: 'Name for the MCP tool (defaults to workflow name)', + }, + workflowId: { type: 'string', description: 'Workflow ID (defaults to active workflow)' }, + }, + required: ['serverId'], + }, requiresConfirmation: true, - requiredPermission: "admin", -}; + requiredPermission: 'admin', +} export const DownloadToWorkspaceFile: ToolCatalogEntry = { - id: "download_to_workspace_file", - name: "download_to_workspace_file", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"fileName":{"type":"string","description":"Optional workspace file name to save as. If omitted, the name is inferred from the response or URL."},"url":{"type":"string","description":"Direct URL of the file to download, such as an image CDN URL ending in .png or .jpg"}},"required":["url"]}, - requiredPermission: "write", -}; + id: 'download_to_workspace_file', + name: 'download_to_workspace_file', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + fileName: { + type: 'string', + description: + 'Optional workspace file name to save as. If omitted, the name is inferred from the response or URL.', + }, + url: { + type: 'string', + description: + 'Direct URL of the file to download, such as an image CDN URL ending in .png or .jpg', + }, + }, + required: ['url'], + }, + requiredPermission: 'write', +} export const EditWorkflow: ToolCatalogEntry = { - id: "edit_workflow", - name: "edit_workflow", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"operations":{"type":"array","description":"Array of edit operations","items":{"type":"object","properties":{"block_id":{"type":"string","description":"Block ID for the operation. For add operations, this will be the desired ID for the new block."},"operation_type":{"type":"string","description":"Type of operation to perform","enum":["add","edit","delete","insert_into_subflow","extract_from_subflow"]},"params":{"type":"object","description":"Parameters for the operation. \nFor edit: {\"inputs\": {\"temperature\": 0.5}} NOT {\"subBlocks\": {\"temperature\": {\"value\": 0.5}}}\nFor add: {\"type\": \"agent\", \"name\": \"My Agent\", \"inputs\": {\"model\": \"gpt-4o\"}}\nFor delete: {} (empty object)"}},"required":["operation_type","block_id","params"]}},"workflowId":{"type":"string","description":"Optional workflow ID to edit. If not provided, uses the current workflow in context."}},"required":["operations"]}, - requiredPermission: "write", -}; + id: 'edit_workflow', + name: 'edit_workflow', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + operations: { + type: 'array', + description: 'Array of edit operations', + items: { + type: 'object', + properties: { + block_id: { + type: 'string', + description: + 'Block ID for the operation. For add operations, this will be the desired ID for the new block.', + }, + operation_type: { + type: 'string', + description: 'Type of operation to perform', + enum: ['add', 'edit', 'delete', 'insert_into_subflow', 'extract_from_subflow'], + }, + params: { + type: 'object', + description: + 'Parameters for the operation. \nFor edit: {"inputs": {"temperature": 0.5}} NOT {"subBlocks": {"temperature": {"value": 0.5}}}\nFor add: {"type": "agent", "name": "My Agent", "inputs": {"model": "gpt-4o"}}\nFor delete: {} (empty object)', + }, + }, + required: ['operation_type', 'block_id', 'params'], + }, + }, + workflowId: { + type: 'string', + description: + 'Optional workflow ID to edit. If not provided, uses the current workflow in context.', + }, + }, + required: ['operations'], + }, + requiredPermission: 'write', +} export const File: ToolCatalogEntry = { - id: "file", - name: "file", - executor: "subagent", - mode: "async", - parameters: {"type":"object"}, - subagentId: "file", + id: 'file', + name: 'file', + executor: 'subagent', + mode: 'async', + parameters: { type: 'object' }, + subagentId: 'file', internal: true, -}; +} export const FunctionExecute: ToolCatalogEntry = { - id: "function_execute", - name: "function_execute", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"code":{"type":"string","description":"Code to execute. For JS: raw statements auto-wrapped in async context. For Python: full script. For shell: bash script with access to pre-installed CLI tools and workspace env vars as $VAR_NAME."},"inputFiles":{"type":"array","description":"Canonical workspace file IDs to mount in the sandbox. Discover IDs via read(\"files/{name}/meta.json\") or glob(\"files/by-id/*/meta.json\"). Mounted path: /home/user/files/{fileId}/{originalName}. Example: [\"wf_123\"]","items":{"type":"string"}},"inputTables":{"type":"array","description":"Table IDs to mount as CSV files in the sandbox. Each table appears at /home/user/tables/{tableId}.csv with a header row. Example: [\"tbl_abc123\"]","items":{"type":"string"}},"language":{"type":"string","description":"Execution language.","enum":["javascript","python","shell"]},"outputFormat":{"type":"string","description":"Format for outputPath. Determines how the code result is serialized. If omitted, inferred from outputPath file extension.","enum":["json","csv","txt","md","html"]},"outputMimeType":{"type":"string","description":"MIME type for outputSandboxPath export. Required for binary files: image/png, image/jpeg, application/pdf, etc. Omit for text files."},"outputPath":{"type":"string","description":"Pipe output directly to a NEW workspace file instead of returning in context. ALWAYS use this instead of a separate workspace_file write call. Use a flat path like \"files/result.json\" — nested paths are not supported."},"outputSandboxPath":{"type":"string","description":"Path to a file created inside the sandbox that should be exported to the workspace. Use together with outputPath."},"outputTable":{"type":"string","description":"Table ID to overwrite with the code's return value. Code MUST return an array of objects where keys match column names. All existing rows are replaced. Example: \"tbl_abc123\""}},"required":["code"]}, - requiredPermission: "write", -}; + id: 'function_execute', + name: 'function_execute', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + code: { + type: 'string', + description: + 'Code to execute. For JS: raw statements auto-wrapped in async context. For Python: full script. For shell: bash script with access to pre-installed CLI tools and workspace env vars as $VAR_NAME.', + }, + inputFiles: { + type: 'array', + description: + 'Canonical workspace file IDs to mount in the sandbox. Discover IDs via read("files/{name}/meta.json") or glob("files/by-id/*/meta.json"). Mounted path: /home/user/files/{fileId}/{originalName}. Example: ["wf_123"]', + items: { type: 'string' }, + }, + inputTables: { + type: 'array', + description: + 'Table IDs to mount as CSV files in the sandbox. Each table appears at /home/user/tables/{tableId}.csv with a header row. Example: ["tbl_abc123"]', + items: { type: 'string' }, + }, + language: { + type: 'string', + description: 'Execution language.', + enum: ['javascript', 'python', 'shell'], + }, + outputFormat: { + type: 'string', + description: + 'Format for outputPath. Determines how the code result is serialized. If omitted, inferred from outputPath file extension.', + enum: ['json', 'csv', 'txt', 'md', 'html'], + }, + outputMimeType: { + type: 'string', + description: + 'MIME type for outputSandboxPath export. Required for binary files: image/png, image/jpeg, application/pdf, etc. Omit for text files.', + }, + outputPath: { + type: 'string', + description: + 'Pipe output directly to a NEW workspace file instead of returning in context. ALWAYS use this instead of a separate workspace_file write call. Use a flat path like "files/result.json" — nested paths are not supported.', + }, + outputSandboxPath: { + type: 'string', + description: + 'Path to a file created inside the sandbox that should be exported to the workspace. Use together with outputPath.', + }, + outputTable: { + type: 'string', + description: + 'Table ID to overwrite with the code\'s return value. Code MUST return an array of objects where keys match column names. All existing rows are replaced. Example: "tbl_abc123"', + }, + }, + required: ['code'], + }, + requiredPermission: 'write', +} export const GenerateApiKey: ToolCatalogEntry = { - id: "generate_api_key", - name: "generate_api_key", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"name":{"type":"string","description":"A descriptive name for the API key (e.g., 'production-key', 'dev-testing')."},"workspaceId":{"type":"string","description":"Optional workspace ID. Defaults to user's default workspace."}},"required":["name"]}, + id: 'generate_api_key', + name: 'generate_api_key', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + name: { + type: 'string', + description: "A descriptive name for the API key (e.g., 'production-key', 'dev-testing').", + }, + workspaceId: { + type: 'string', + description: "Optional workspace ID. Defaults to user's default workspace.", + }, + }, + required: ['name'], + }, requiresConfirmation: true, - requiredPermission: "admin", -}; + requiredPermission: 'admin', +} export const GenerateImage: ToolCatalogEntry = { - id: "generate_image", - name: "generate_image", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"aspectRatio":{"type":"string","description":"Aspect ratio for the generated image.","enum":["1:1","16:9","9:16","4:3","3:4"]},"fileName":{"type":"string","description":"Output file name. Defaults to \"generated-image.png\". Workspace files are flat, so pass a plain file name, not a nested path."},"overwriteFileId":{"type":"string","description":"If provided, overwrites the existing workspace file with this ID instead of creating a new file. Use this when the user asks to update or redo a previously generated image. The file ID is returned by previous generate_image or generate_visualization calls (fileId field), or can be found via read(\"files/by-id/{fileId}/meta.json\")."},"prompt":{"type":"string","description":"Detailed text description of the image to generate, or editing instructions when used with editFileId."},"referenceFileIds":{"type":"array","description":"File IDs of workspace images to include as context for the generation. All images are sent alongside the prompt. Use for: editing a single image (1 file), compositing multiple images together (2+ files), style transfer, face swapping, etc. Order matters — list the primary/base image first.","items":{"type":"string"}}},"required":["prompt"]}, - requiredPermission: "write", -}; + id: 'generate_image', + name: 'generate_image', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + aspectRatio: { + type: 'string', + description: 'Aspect ratio for the generated image.', + enum: ['1:1', '16:9', '9:16', '4:3', '3:4'], + }, + fileName: { + type: 'string', + description: + 'Output file name. Defaults to "generated-image.png". Workspace files are flat, so pass a plain file name, not a nested path.', + }, + overwriteFileId: { + type: 'string', + description: + 'If provided, overwrites the existing workspace file with this ID instead of creating a new file. Use this when the user asks to update or redo a previously generated image. The file ID is returned by previous generate_image or generate_visualization calls (fileId field), or can be found via read("files/by-id/{fileId}/meta.json").', + }, + prompt: { + type: 'string', + description: + 'Detailed text description of the image to generate, or editing instructions when used with editFileId.', + }, + referenceFileIds: { + type: 'array', + description: + 'File IDs of workspace images to include as context for the generation. All images are sent alongside the prompt. Use for: editing a single image (1 file), compositing multiple images together (2+ files), style transfer, face swapping, etc. Order matters — list the primary/base image first.', + items: { type: 'string' }, + }, + }, + required: ['prompt'], + }, + requiredPermission: 'write', +} export const GenerateVisualization: ToolCatalogEntry = { - id: "generate_visualization", - name: "generate_visualization", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"code":{"type":"string","description":"Python code that generates a visualization using matplotlib. MUST call plt.savefig('/home/user/output.png', dpi=150, bbox_inches='tight') to produce output."},"fileName":{"type":"string","description":"Output file name. Defaults to \"chart.png\". Workspace files are flat, so pass a plain file name, not a nested path."},"inputFiles":{"type":"array","description":"Canonical workspace file IDs to mount in the sandbox. Discover IDs via read(\"files/{name}/meta.json\") or glob(\"files/by-id/*/meta.json\"). Mounted path: /home/user/files/{fileId}/{originalName}.","items":{"type":"string"}},"inputTables":{"type":"array","description":"Table IDs to mount as CSV files in the sandbox. Each table appears at /home/user/tables/{tableId}.csv with a header row. Read with pandas: pd.read_csv('/home/user/tables/tbl_xxx.csv')","items":{"type":"string"}},"overwriteFileId":{"type":"string","description":"If provided, overwrites the existing workspace file with this ID instead of creating a new file. Use this when the user asks to update or redo a previously generated chart. The file ID is returned by previous generate_visualization or generate_image calls (fileId field), or can be found via read(\"files/by-id/{fileId}/meta.json\")."}},"required":["code"]}, - requiredPermission: "write", -}; + id: 'generate_visualization', + name: 'generate_visualization', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + code: { + type: 'string', + description: + "Python code that generates a visualization using matplotlib. MUST call plt.savefig('/home/user/output.png', dpi=150, bbox_inches='tight') to produce output.", + }, + fileName: { + type: 'string', + description: + 'Output file name. Defaults to "chart.png". Workspace files are flat, so pass a plain file name, not a nested path.', + }, + inputFiles: { + type: 'array', + description: + 'Canonical workspace file IDs to mount in the sandbox. Discover IDs via read("files/{name}/meta.json") or glob("files/by-id/*/meta.json"). Mounted path: /home/user/files/{fileId}/{originalName}.', + items: { type: 'string' }, + }, + inputTables: { + type: 'array', + description: + "Table IDs to mount as CSV files in the sandbox. Each table appears at /home/user/tables/{tableId}.csv with a header row. Read with pandas: pd.read_csv('/home/user/tables/tbl_xxx.csv')", + items: { type: 'string' }, + }, + overwriteFileId: { + type: 'string', + description: + 'If provided, overwrites the existing workspace file with this ID instead of creating a new file. Use this when the user asks to update or redo a previously generated chart. The file ID is returned by previous generate_visualization or generate_image calls (fileId field), or can be found via read("files/by-id/{fileId}/meta.json").', + }, + }, + required: ['code'], + }, + requiredPermission: 'write', +} export const GetBlockOutputs: ToolCatalogEntry = { - id: "get_block_outputs", - name: "get_block_outputs", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"blockIds":{"type":"array","description":"Optional array of block UUIDs. If provided, returns outputs only for those blocks. If not provided, returns outputs for all blocks in the workflow.","items":{"type":"string"}},"workflowId":{"type":"string","description":"Optional workflow ID. If not provided, uses the current workflow in context."}}}, -}; + id: 'get_block_outputs', + name: 'get_block_outputs', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + blockIds: { + type: 'array', + description: + 'Optional array of block UUIDs. If provided, returns outputs only for those blocks. If not provided, returns outputs for all blocks in the workflow.', + items: { type: 'string' }, + }, + workflowId: { + type: 'string', + description: 'Optional workflow ID. If not provided, uses the current workflow in context.', + }, + }, + }, +} export const GetBlockUpstreamReferences: ToolCatalogEntry = { - id: "get_block_upstream_references", - name: "get_block_upstream_references", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"blockIds":{"type":"array","description":"Required array of block UUIDs (minimum 1). Returns what each block can reference based on its position in the workflow graph.","items":{"type":"string"}},"workflowId":{"type":"string","description":"Optional workflow ID. If not provided, uses the current workflow in context."}},"required":["blockIds"]}, -}; + id: 'get_block_upstream_references', + name: 'get_block_upstream_references', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + blockIds: { + type: 'array', + description: + 'Required array of block UUIDs (minimum 1). Returns what each block can reference based on its position in the workflow graph.', + items: { type: 'string' }, + }, + workflowId: { + type: 'string', + description: 'Optional workflow ID. If not provided, uses the current workflow in context.', + }, + }, + required: ['blockIds'], + }, +} export const GetDeployedWorkflowState: ToolCatalogEntry = { - id: "get_deployed_workflow_state", - name: "get_deployed_workflow_state", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"workflowId":{"type":"string","description":"Optional workflow ID. If not provided, uses the current workflow in context."}}}, -}; + id: 'get_deployed_workflow_state', + name: 'get_deployed_workflow_state', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + workflowId: { + type: 'string', + description: 'Optional workflow ID. If not provided, uses the current workflow in context.', + }, + }, + }, +} export const GetDeploymentVersion: ToolCatalogEntry = { - id: "get_deployment_version", - name: "get_deployment_version", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"version":{"type":"number","description":"The deployment version number"},"workflowId":{"type":"string","description":"The workflow ID"}},"required":["workflowId","version"]}, -}; + id: 'get_deployment_version', + name: 'get_deployment_version', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + version: { type: 'number', description: 'The deployment version number' }, + workflowId: { type: 'string', description: 'The workflow ID' }, + }, + required: ['workflowId', 'version'], + }, +} export const GetExecutionSummary: ToolCatalogEntry = { - id: "get_execution_summary", - name: "get_execution_summary", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"limit":{"type":"number","description":"Max number of executions to return (default: 10, max: 20)."},"status":{"type":"string","description":"Filter by status: 'success', 'error', or 'all' (default: 'all').","enum":["success","error","all"]},"workflowId":{"type":"string","description":"Optional workflow ID. If omitted, returns executions across all workflows in the workspace."},"workspaceId":{"type":"string","description":"Workspace ID to scope executions to."}},"required":["workspaceId"]}, -}; + id: 'get_execution_summary', + name: 'get_execution_summary', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + limit: { + type: 'number', + description: 'Max number of executions to return (default: 10, max: 20).', + }, + status: { + type: 'string', + description: "Filter by status: 'success', 'error', or 'all' (default: 'all').", + enum: ['success', 'error', 'all'], + }, + workflowId: { + type: 'string', + description: + 'Optional workflow ID. If omitted, returns executions across all workflows in the workspace.', + }, + workspaceId: { type: 'string', description: 'Workspace ID to scope executions to.' }, + }, + required: ['workspaceId'], + }, +} export const GetJobLogs: ToolCatalogEntry = { - id: "get_job_logs", - name: "get_job_logs", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"executionId":{"type":"string","description":"Optional execution ID for a specific run."},"includeDetails":{"type":"boolean","description":"Include tool calls, outputs, and cost details."},"jobId":{"type":"string","description":"The job (schedule) ID to get logs for."},"limit":{"type":"number","description":"Max number of entries (default: 3, max: 5)"}},"required":["jobId"]}, -}; + id: 'get_job_logs', + name: 'get_job_logs', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + executionId: { type: 'string', description: 'Optional execution ID for a specific run.' }, + includeDetails: { + type: 'boolean', + description: 'Include tool calls, outputs, and cost details.', + }, + jobId: { type: 'string', description: 'The job (schedule) ID to get logs for.' }, + limit: { type: 'number', description: 'Max number of entries (default: 3, max: 5)' }, + }, + required: ['jobId'], + }, +} export const GetPageContents: ToolCatalogEntry = { - id: "get_page_contents", - name: "get_page_contents", - executor: "go", - mode: "sync", - parameters: {"type":"object","properties":{"include_highlights":{"type":"boolean","description":"Include key highlights (default false)"},"include_summary":{"type":"boolean","description":"Include AI-generated summary (default false)"},"include_text":{"type":"boolean","description":"Include full page text (default true)"},"urls":{"type":"array","description":"URLs to get content from (max 10)","items":{"type":"string"}}},"required":["urls"]}, -}; + id: 'get_page_contents', + name: 'get_page_contents', + executor: 'go', + mode: 'sync', + parameters: { + type: 'object', + properties: { + include_highlights: { + type: 'boolean', + description: 'Include key highlights (default false)', + }, + include_summary: { + type: 'boolean', + description: 'Include AI-generated summary (default false)', + }, + include_text: { type: 'boolean', description: 'Include full page text (default true)' }, + urls: { + type: 'array', + description: 'URLs to get content from (max 10)', + items: { type: 'string' }, + }, + }, + required: ['urls'], + }, +} export const GetPlatformActions: ToolCatalogEntry = { - id: "get_platform_actions", - name: "get_platform_actions", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{}}, -}; + id: 'get_platform_actions', + name: 'get_platform_actions', + executor: 'sim', + mode: 'async', + parameters: { type: 'object', properties: {} }, +} export const GetWorkflowData: ToolCatalogEntry = { - id: "get_workflow_data", - name: "get_workflow_data", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"data_type":{"type":"string","description":"The type of workflow data to retrieve","enum":["global_variables","custom_tools","mcp_tools","files"]},"workflowId":{"type":"string","description":"Optional workflow ID. If not provided, uses the current workflow in context."}},"required":["data_type"]}, -}; + id: 'get_workflow_data', + name: 'get_workflow_data', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + data_type: { + type: 'string', + description: 'The type of workflow data to retrieve', + enum: ['global_variables', 'custom_tools', 'mcp_tools', 'files'], + }, + workflowId: { + type: 'string', + description: 'Optional workflow ID. If not provided, uses the current workflow in context.', + }, + }, + required: ['data_type'], + }, +} export const GetWorkflowLogs: ToolCatalogEntry = { - id: "get_workflow_logs", - name: "get_workflow_logs", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"executionId":{"type":"string","description":"Optional execution ID to get logs for a specific execution. Use with get_execution_summary to find execution IDs first."},"includeDetails":{"type":"boolean","description":"Include detailed info"},"limit":{"type":"number","description":"Max number of entries (hard limit: 3)"},"workflowId":{"type":"string","description":"Optional workflow ID. If not provided, uses the current workflow in context."}}}, -}; + id: 'get_workflow_logs', + name: 'get_workflow_logs', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + executionId: { + type: 'string', + description: + 'Optional execution ID to get logs for a specific execution. Use with get_execution_summary to find execution IDs first.', + }, + includeDetails: { type: 'boolean', description: 'Include detailed info' }, + limit: { type: 'number', description: 'Max number of entries (hard limit: 3)' }, + workflowId: { + type: 'string', + description: 'Optional workflow ID. If not provided, uses the current workflow in context.', + }, + }, + }, +} export const Glob: ToolCatalogEntry = { - id: "glob", - name: "glob", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"pattern":{"type":"string","description":"Glob pattern to match file paths. Supports * (any segment) and ** (any depth)."}},"required":["pattern"]}, -}; + id: 'glob', + name: 'glob', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + pattern: { + type: 'string', + description: + 'Glob pattern to match file paths. Supports * (any segment) and ** (any depth).', + }, + }, + required: ['pattern'], + }, +} export const Grep: ToolCatalogEntry = { - id: "grep", - name: "grep", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"context":{"type":"number","description":"Number of lines to show before and after each match. Only applies to output_mode 'content'."},"ignoreCase":{"type":"boolean","description":"Case insensitive search (default false)."},"lineNumbers":{"type":"boolean","description":"Include line numbers in output (default true). Only applies to output_mode 'content'."},"maxResults":{"type":"number","description":"Maximum number of matches to return (default 50)."},"output_mode":{"type":"string","description":"Output mode: 'content' shows matching lines (default), 'files_with_matches' shows only file paths, 'count' shows match counts per file.","enum":["content","files_with_matches","count"]},"path":{"type":"string","description":"Optional path prefix to scope the search (e.g. 'workflows/', 'environment/', 'internal/', 'components/blocks/')."},"pattern":{"type":"string","description":"Regex pattern to search for in file contents."}},"required":["pattern"]}, -}; + id: 'grep', + name: 'grep', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + context: { + type: 'number', + description: + "Number of lines to show before and after each match. Only applies to output_mode 'content'.", + }, + ignoreCase: { type: 'boolean', description: 'Case insensitive search (default false).' }, + lineNumbers: { + type: 'boolean', + description: + "Include line numbers in output (default true). Only applies to output_mode 'content'.", + }, + maxResults: { + type: 'number', + description: 'Maximum number of matches to return (default 50).', + }, + output_mode: { + type: 'string', + description: + "Output mode: 'content' shows matching lines (default), 'files_with_matches' shows only file paths, 'count' shows match counts per file.", + enum: ['content', 'files_with_matches', 'count'], + }, + path: { + type: 'string', + description: + "Optional path prefix to scope the search (e.g. 'workflows/', 'environment/', 'internal/', 'components/blocks/').", + }, + pattern: { type: 'string', description: 'Regex pattern to search for in file contents.' }, + }, + required: ['pattern'], + }, +} export const Job: ToolCatalogEntry = { - id: "job", - name: "job", - executor: "subagent", - mode: "async", - parameters: {"properties":{"request":{"description":"What job action is needed.","type":"string"}},"required":["request"],"type":"object"}, - subagentId: "job", + id: 'job', + name: 'job', + executor: 'subagent', + mode: 'async', + parameters: { + properties: { request: { description: 'What job action is needed.', type: 'string' } }, + required: ['request'], + type: 'object', + }, + subagentId: 'job', internal: true, -}; +} export const Knowledge: ToolCatalogEntry = { - id: "knowledge", - name: "knowledge", - executor: "subagent", - mode: "async", - parameters: {"properties":{"request":{"description":"What knowledge base action is needed.","type":"string"}},"required":["request"],"type":"object"}, - subagentId: "knowledge", + id: 'knowledge', + name: 'knowledge', + executor: 'subagent', + mode: 'async', + parameters: { + properties: { + request: { description: 'What knowledge base action is needed.', type: 'string' }, + }, + required: ['request'], + type: 'object', + }, + subagentId: 'knowledge', internal: true, -}; +} export const KnowledgeBase: ToolCatalogEntry = { - id: "knowledge_base", - name: "knowledge_base", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"args":{"type":"object","description":"Arguments for the operation","properties":{"apiKey":{"type":"string","description":"API key for API-key-based connectors (required when connector auth mode is apiKey)"},"chunkingConfig":{"type":"object","description":"Chunking configuration (optional for 'create')","properties":{"maxSize":{"type":"number","description":"Maximum chunk size (100-4000, default: 1024)","default":1024},"minSize":{"type":"number","description":"Minimum chunk size (1-2000, default: 1)","default":1},"overlap":{"type":"number","description":"Overlap between chunks (0-500, default: 200)","default":200}}},"connectorId":{"type":"string","description":"Connector ID (required for update_connector, delete_connector, sync_connector)"},"connectorStatus":{"type":"string","description":"Connector status (optional for update_connector)","enum":["active","paused"]},"connectorType":{"type":"string","description":"Connector type from registry, e.g. 'confluence', 'google_drive', 'notion' (required for add_connector). Read knowledgebases/connectors/{type}.json for the config schema."},"credentialId":{"type":"string","description":"OAuth credential ID from environment/credentials.json (required for OAuth connectors)"},"description":{"type":"string","description":"Description of the knowledge base (optional for 'create')"},"disabledTagIds":{"type":"array","description":"Tag definition IDs to opt out of (optional for add_connector). See tagDefinitions in the connector schema."},"documentId":{"type":"string","description":"Document ID (required for delete_document, update_document)"},"enabled":{"type":"boolean","description":"Enable/disable a document (optional for update_document)"},"fileId":{"type":"string","description":"Canonical workspace file ID to add as a document (preferred for add_file). Discover via read(\"files/{name}/meta.json\") or glob(\"files/by-id/*/meta.json\")."},"filePath":{"type":"string","description":"Legacy workspace file reference for add_file. Prefer fileId."},"filename":{"type":"string","description":"New filename for a document (optional for update_document)"},"knowledgeBaseId":{"type":"string","description":"Knowledge base ID (required for get, query, add_file, list_tags, create_tag, get_tag_usage)"},"name":{"type":"string","description":"Name of the knowledge base (required for 'create')"},"query":{"type":"string","description":"Search query text (required for 'query')"},"sourceConfig":{"type":"object","description":"Connector-specific configuration matching the configFields in knowledgebases/connectors/{type}.json"},"syncIntervalMinutes":{"type":"number","description":"Sync interval in minutes: 60 (hourly), 360 (6h), 1440 (daily), 10080 (weekly), 0 (manual only). Default: 1440","default":1440},"tagDefinitionId":{"type":"string","description":"Tag definition ID (required for update_tag, delete_tag)"},"tagDisplayName":{"type":"string","description":"Display name for the tag (required for create_tag, optional for update_tag)"},"tagFieldType":{"type":"string","description":"Field type: text, number, date, boolean (optional for create_tag, defaults to text)","enum":["text","number","date","boolean"]},"topK":{"type":"number","description":"Number of results to return (1-50, default: 5)","default":5},"workspaceId":{"type":"string","description":"Workspace ID (required for 'create', optional filter for 'list')"}}},"operation":{"type":"string","description":"The operation to perform","enum":["create","get","query","add_file","update","delete","delete_document","update_document","list_tags","create_tag","update_tag","delete_tag","get_tag_usage","add_connector","update_connector","delete_connector","sync_connector"]}},"required":["operation","args"]}, - resultSchema: {"type":"object","properties":{"data":{"type":"object","description":"Operation-specific result payload."},"message":{"type":"string","description":"Human-readable outcome summary."},"success":{"type":"boolean","description":"Whether the operation succeeded."}},"required":["success","message"]}, + id: 'knowledge_base', + name: 'knowledge_base', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + args: { + type: 'object', + description: 'Arguments for the operation', + properties: { + apiKey: { + type: 'string', + description: + 'API key for API-key-based connectors (required when connector auth mode is apiKey)', + }, + chunkingConfig: { + type: 'object', + description: "Chunking configuration (optional for 'create')", + properties: { + maxSize: { + type: 'number', + description: 'Maximum chunk size (100-4000, default: 1024)', + default: 1024, + }, + minSize: { + type: 'number', + description: 'Minimum chunk size (1-2000, default: 1)', + default: 1, + }, + overlap: { + type: 'number', + description: 'Overlap between chunks (0-500, default: 200)', + default: 200, + }, + }, + }, + connectorId: { + type: 'string', + description: + 'Connector ID (required for update_connector, delete_connector, sync_connector)', + }, + connectorStatus: { + type: 'string', + description: 'Connector status (optional for update_connector)', + enum: ['active', 'paused'], + }, + connectorType: { + type: 'string', + description: + "Connector type from registry, e.g. 'confluence', 'google_drive', 'notion' (required for add_connector). Read knowledgebases/connectors/{type}.json for the config schema.", + }, + credentialId: { + type: 'string', + description: + 'OAuth credential ID from environment/credentials.json (required for OAuth connectors)', + }, + description: { + type: 'string', + description: "Description of the knowledge base (optional for 'create')", + }, + disabledTagIds: { + type: 'array', + description: + 'Tag definition IDs to opt out of (optional for add_connector). See tagDefinitions in the connector schema.', + }, + documentId: { + type: 'string', + description: 'Document ID (required for delete_document, update_document)', + }, + enabled: { + type: 'boolean', + description: 'Enable/disable a document (optional for update_document)', + }, + fileId: { + type: 'string', + description: + 'Canonical workspace file ID to add as a document (preferred for add_file). Discover via read("files/{name}/meta.json") or glob("files/by-id/*/meta.json").', + }, + filePath: { + type: 'string', + description: 'Legacy workspace file reference for add_file. Prefer fileId.', + }, + filename: { + type: 'string', + description: 'New filename for a document (optional for update_document)', + }, + knowledgeBaseId: { + type: 'string', + description: + 'Knowledge base ID (required for get, query, add_file, list_tags, create_tag, get_tag_usage)', + }, + name: { + type: 'string', + description: "Name of the knowledge base (required for 'create')", + }, + query: { type: 'string', description: "Search query text (required for 'query')" }, + sourceConfig: { + type: 'object', + description: + 'Connector-specific configuration matching the configFields in knowledgebases/connectors/{type}.json', + }, + syncIntervalMinutes: { + type: 'number', + description: + 'Sync interval in minutes: 60 (hourly), 360 (6h), 1440 (daily), 10080 (weekly), 0 (manual only). Default: 1440', + default: 1440, + }, + tagDefinitionId: { + type: 'string', + description: 'Tag definition ID (required for update_tag, delete_tag)', + }, + tagDisplayName: { + type: 'string', + description: + 'Display name for the tag (required for create_tag, optional for update_tag)', + }, + tagFieldType: { + type: 'string', + description: + 'Field type: text, number, date, boolean (optional for create_tag, defaults to text)', + enum: ['text', 'number', 'date', 'boolean'], + }, + topK: { + type: 'number', + description: 'Number of results to return (1-50, default: 5)', + default: 5, + }, + workspaceId: { + type: 'string', + description: "Workspace ID (required for 'create', optional filter for 'list')", + }, + }, + }, + operation: { + type: 'string', + description: 'The operation to perform', + enum: [ + 'create', + 'get', + 'query', + 'add_file', + 'update', + 'delete', + 'delete_document', + 'update_document', + 'list_tags', + 'create_tag', + 'update_tag', + 'delete_tag', + 'get_tag_usage', + 'add_connector', + 'update_connector', + 'delete_connector', + 'sync_connector', + ], + }, + }, + required: ['operation', 'args'], + }, + resultSchema: { + type: 'object', + properties: { + data: { type: 'object', description: 'Operation-specific result payload.' }, + message: { type: 'string', description: 'Human-readable outcome summary.' }, + success: { type: 'boolean', description: 'Whether the operation succeeded.' }, + }, + required: ['success', 'message'], + }, requiresConfirmation: true, -}; +} export const ListFolders: ToolCatalogEntry = { - id: "list_folders", - name: "list_folders", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"workspaceId":{"type":"string","description":"Optional workspace ID to list folders for."}}}, -}; + id: 'list_folders', + name: 'list_folders', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + workspaceId: { type: 'string', description: 'Optional workspace ID to list folders for.' }, + }, + }, +} export const ListUserWorkspaces: ToolCatalogEntry = { - id: "list_user_workspaces", - name: "list_user_workspaces", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{}}, -}; + id: 'list_user_workspaces', + name: 'list_user_workspaces', + executor: 'sim', + mode: 'async', + parameters: { type: 'object', properties: {} }, +} export const ListWorkspaceMcpServers: ToolCatalogEntry = { - id: "list_workspace_mcp_servers", - name: "list_workspace_mcp_servers", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"workspaceId":{"type":"string","description":"Workspace ID (defaults to current workspace)"}}}, -}; + id: 'list_workspace_mcp_servers', + name: 'list_workspace_mcp_servers', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + workspaceId: { type: 'string', description: 'Workspace ID (defaults to current workspace)' }, + }, + }, +} export const ManageCredential: ToolCatalogEntry = { - id: "manage_credential", - name: "manage_credential", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"credentialId":{"type":"string","description":"The credential ID (from environment/credentials.json)"},"displayName":{"type":"string","description":"New display name (required for rename)"},"operation":{"type":"string","description":"The operation to perform","enum":["rename","delete"]}},"required":["operation","credentialId"]}, + id: 'manage_credential', + name: 'manage_credential', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + credentialId: { + type: 'string', + description: 'The credential ID (from environment/credentials.json)', + }, + displayName: { type: 'string', description: 'New display name (required for rename)' }, + operation: { + type: 'string', + description: 'The operation to perform', + enum: ['rename', 'delete'], + }, + }, + required: ['operation', 'credentialId'], + }, requiresConfirmation: true, - requiredPermission: "admin", -}; + requiredPermission: 'admin', +} export const ManageCustomTool: ToolCatalogEntry = { - id: "manage_custom_tool", - name: "manage_custom_tool", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"code":{"type":"string","description":"The JavaScript code that executes when the tool is called (required for add). Parameters from schema are available as variables. Function body only - no signature or wrapping braces."},"operation":{"type":"string","description":"The operation to perform: 'add', 'edit', 'list', or 'delete'","enum":["add","edit","delete","list"]},"schema":{"type":"object","description":"The tool schema in OpenAI function calling format (required for add).","properties":{"function":{"type":"object","description":"The function definition","properties":{"description":{"type":"string","description":"What the function does"},"name":{"type":"string","description":"The function name (camelCase)"},"parameters":{"type":"object","description":"The function parameters schema","properties":{"properties":{"type":"object","description":"Parameter definitions as key-value pairs"},"required":{"type":"array","description":"Array of required parameter names","items":{"type":"string"}},"type":{"type":"string","description":"Must be 'object'"}},"required":["type","properties"]}},"required":["name","parameters"]},"type":{"type":"string","description":"Must be 'function'"}},"required":["type","function"]},"toolId":{"type":"string","description":"The ID of the custom tool (required for edit/delete). Must be the exact toolId from the get_workflow_data custom tool response - do not guess or construct it. DO NOT PROVIDE THE TOOL ID IF THE OPERATION IS 'ADD'."}},"required":["operation"]}, + id: 'manage_custom_tool', + name: 'manage_custom_tool', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + code: { + type: 'string', + description: + 'The JavaScript code that executes when the tool is called (required for add). Parameters from schema are available as variables. Function body only - no signature or wrapping braces.', + }, + operation: { + type: 'string', + description: "The operation to perform: 'add', 'edit', 'list', or 'delete'", + enum: ['add', 'edit', 'delete', 'list'], + }, + schema: { + type: 'object', + description: 'The tool schema in OpenAI function calling format (required for add).', + properties: { + function: { + type: 'object', + description: 'The function definition', + properties: { + description: { type: 'string', description: 'What the function does' }, + name: { type: 'string', description: 'The function name (camelCase)' }, + parameters: { + type: 'object', + description: 'The function parameters schema', + properties: { + properties: { + type: 'object', + description: 'Parameter definitions as key-value pairs', + }, + required: { + type: 'array', + description: 'Array of required parameter names', + items: { type: 'string' }, + }, + type: { type: 'string', description: "Must be 'object'" }, + }, + required: ['type', 'properties'], + }, + }, + required: ['name', 'parameters'], + }, + type: { type: 'string', description: "Must be 'function'" }, + }, + required: ['type', 'function'], + }, + toolId: { + type: 'string', + description: + "The ID of the custom tool (required for edit/delete). Must be the exact toolId from the get_workflow_data custom tool response - do not guess or construct it. DO NOT PROVIDE THE TOOL ID IF THE OPERATION IS 'ADD'.", + }, + }, + required: ['operation'], + }, requiresConfirmation: true, -}; +} export const ManageJob: ToolCatalogEntry = { - id: "manage_job", - name: "manage_job", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"args":{"type":"object","description":"Operation-specific arguments. For create: {title, prompt, cron?, time?, timezone?, lifecycle?, successCondition?, maxRuns?}. For get/delete: {jobId}. For update: {jobId, title?, prompt?, cron?, timezone?, status?, lifecycle?, successCondition?, maxRuns?}. For list: no args needed.","properties":{"cron":{"type":"string","description":"Cron expression for recurring jobs"},"jobId":{"type":"string","description":"Job ID (required for get, update, delete)"},"lifecycle":{"type":"string","description":"'persistent' (default) or 'until_complete'. Until_complete jobs stop when complete_job is called."},"maxRuns":{"type":"integer","description":"Max executions before auto-completing. Safety limit."},"prompt":{"type":"string","description":"The prompt to execute when the job fires"},"status":{"type":"string","description":"Job status: active, paused"},"successCondition":{"type":"string","description":"What must happen for the job to be considered complete (until_complete lifecycle)."},"time":{"type":"string","description":"ISO 8601 datetime for one-time jobs or cron start time"},"timezone":{"type":"string","description":"IANA timezone (e.g. America/New_York). Defaults to UTC."},"title":{"type":"string","description":"Short descriptive title for the job (e.g. 'Email Poller')"}}},"operation":{"type":"string","description":"The operation to perform: create, list, get, update, delete","enum":["create","list","get","update","delete"]}},"required":["operation"]}, -}; + id: 'manage_job', + name: 'manage_job', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + args: { + type: 'object', + description: + 'Operation-specific arguments. For create: {title, prompt, cron?, time?, timezone?, lifecycle?, successCondition?, maxRuns?}. For get/delete: {jobId}. For update: {jobId, title?, prompt?, cron?, timezone?, status?, lifecycle?, successCondition?, maxRuns?}. For list: no args needed.', + properties: { + cron: { type: 'string', description: 'Cron expression for recurring jobs' }, + jobId: { type: 'string', description: 'Job ID (required for get, update, delete)' }, + lifecycle: { + type: 'string', + description: + "'persistent' (default) or 'until_complete'. Until_complete jobs stop when complete_job is called.", + }, + maxRuns: { + type: 'integer', + description: 'Max executions before auto-completing. Safety limit.', + }, + prompt: { type: 'string', description: 'The prompt to execute when the job fires' }, + status: { type: 'string', description: 'Job status: active, paused' }, + successCondition: { + type: 'string', + description: + 'What must happen for the job to be considered complete (until_complete lifecycle).', + }, + time: { + type: 'string', + description: 'ISO 8601 datetime for one-time jobs or cron start time', + }, + timezone: { + type: 'string', + description: 'IANA timezone (e.g. America/New_York). Defaults to UTC.', + }, + title: { + type: 'string', + description: "Short descriptive title for the job (e.g. 'Email Poller')", + }, + }, + }, + operation: { + type: 'string', + description: 'The operation to perform: create, list, get, update, delete', + enum: ['create', 'list', 'get', 'update', 'delete'], + }, + }, + required: ['operation'], + }, +} export const ManageMcpTool: ToolCatalogEntry = { - id: "manage_mcp_tool", - name: "manage_mcp_tool", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"config":{"type":"object","description":"Required for add and edit. The MCP server configuration.","properties":{"enabled":{"type":"boolean","description":"Whether the server is enabled (default: true)"},"headers":{"type":"object","description":"Optional HTTP headers to send with requests (key-value pairs)"},"name":{"type":"string","description":"Display name for the MCP server"},"timeout":{"type":"number","description":"Request timeout in milliseconds (default: 30000)"},"transport":{"type":"string","description":"Transport protocol: 'streamable-http' or 'sse'","enum":["streamable-http","sse"],"default":"streamable-http"},"url":{"type":"string","description":"The MCP server endpoint URL (required for add)"}}},"operation":{"type":"string","description":"The operation to perform: 'add', 'edit', 'list', or 'delete'","enum":["add","edit","delete","list"]},"serverId":{"type":"string","description":"Required for edit and delete. The database ID of the MCP server. DO NOT PROVIDE if operation is 'add' or 'list'."}},"required":["operation"]}, + id: 'manage_mcp_tool', + name: 'manage_mcp_tool', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + config: { + type: 'object', + description: 'Required for add and edit. The MCP server configuration.', + properties: { + enabled: { + type: 'boolean', + description: 'Whether the server is enabled (default: true)', + }, + headers: { + type: 'object', + description: 'Optional HTTP headers to send with requests (key-value pairs)', + }, + name: { type: 'string', description: 'Display name for the MCP server' }, + timeout: { + type: 'number', + description: 'Request timeout in milliseconds (default: 30000)', + }, + transport: { + type: 'string', + description: "Transport protocol: 'streamable-http' or 'sse'", + enum: ['streamable-http', 'sse'], + default: 'streamable-http', + }, + url: { type: 'string', description: 'The MCP server endpoint URL (required for add)' }, + }, + }, + operation: { + type: 'string', + description: "The operation to perform: 'add', 'edit', 'list', or 'delete'", + enum: ['add', 'edit', 'delete', 'list'], + }, + serverId: { + type: 'string', + description: + "Required for edit and delete. The database ID of the MCP server. DO NOT PROVIDE if operation is 'add' or 'list'.", + }, + }, + required: ['operation'], + }, requiresConfirmation: true, - requiredPermission: "write", -}; + requiredPermission: 'write', +} export const ManageSkill: ToolCatalogEntry = { - id: "manage_skill", - name: "manage_skill", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"content":{"type":"string","description":"Markdown instructions for the skill. Required for add, optional for edit."},"description":{"type":"string","description":"Short description of the skill. Required for add, optional for edit."},"name":{"type":"string","description":"Skill name in kebab-case (e.g. 'my-skill'). Required for add, optional for edit."},"operation":{"type":"string","description":"The operation to perform: 'add', 'edit', 'list', or 'delete'","enum":["add","edit","delete","list"]},"skillId":{"type":"string","description":"The ID of the skill (required for edit/delete). Must be the exact ID from the VFS or list. DO NOT PROVIDE if operation is 'add' or 'list'."}},"required":["operation"]}, + id: 'manage_skill', + name: 'manage_skill', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + content: { + type: 'string', + description: 'Markdown instructions for the skill. Required for add, optional for edit.', + }, + description: { + type: 'string', + description: 'Short description of the skill. Required for add, optional for edit.', + }, + name: { + type: 'string', + description: + "Skill name in kebab-case (e.g. 'my-skill'). Required for add, optional for edit.", + }, + operation: { + type: 'string', + description: "The operation to perform: 'add', 'edit', 'list', or 'delete'", + enum: ['add', 'edit', 'delete', 'list'], + }, + skillId: { + type: 'string', + description: + "The ID of the skill (required for edit/delete). Must be the exact ID from the VFS or list. DO NOT PROVIDE if operation is 'add' or 'list'.", + }, + }, + required: ['operation'], + }, requiresConfirmation: true, - requiredPermission: "write", -}; + requiredPermission: 'write', +} export const MaterializeFile: ToolCatalogEntry = { - id: "materialize_file", - name: "materialize_file", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"fileName":{"type":"string","description":"The name of the uploaded file to materialize (e.g. \"report.pdf\")"},"knowledgeBaseId":{"type":"string","description":"ID of an existing knowledge base to add the file to (only used with operation \"knowledge_base\"). If omitted, a new KB is created."},"operation":{"type":"string","description":"What to do with the file. \"save\" promotes it to files/. \"import\" imports a workflow JSON. \"table\" converts CSV/TSV/JSON to a table. \"knowledge_base\" saves and adds to a KB. Defaults to \"save\".","enum":["save","import","table","knowledge_base"],"default":"save"},"tableName":{"type":"string","description":"Custom name for the table (only used with operation \"table\"). Defaults to the file name without extension."}},"required":["fileName"]}, - requiredPermission: "write", -}; + id: 'materialize_file', + name: 'materialize_file', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + fileName: { + type: 'string', + description: 'The name of the uploaded file to materialize (e.g. "report.pdf")', + }, + knowledgeBaseId: { + type: 'string', + description: + 'ID of an existing knowledge base to add the file to (only used with operation "knowledge_base"). If omitted, a new KB is created.', + }, + operation: { + type: 'string', + description: + 'What to do with the file. "save" promotes it to files/. "import" imports a workflow JSON. "table" converts CSV/TSV/JSON to a table. "knowledge_base" saves and adds to a KB. Defaults to "save".', + enum: ['save', 'import', 'table', 'knowledge_base'], + default: 'save', + }, + tableName: { + type: 'string', + description: + 'Custom name for the table (only used with operation "table"). Defaults to the file name without extension.', + }, + }, + required: ['fileName'], + }, + requiredPermission: 'write', +} export const MoveFolder: ToolCatalogEntry = { - id: "move_folder", - name: "move_folder", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"folderId":{"type":"string","description":"The folder ID to move."},"parentId":{"type":"string","description":"Target parent folder ID. Omit or pass empty string to move to workspace root."}},"required":["folderId"]}, - requiredPermission: "write", -}; + id: 'move_folder', + name: 'move_folder', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + folderId: { type: 'string', description: 'The folder ID to move.' }, + parentId: { + type: 'string', + description: + 'Target parent folder ID. Omit or pass empty string to move to workspace root.', + }, + }, + required: ['folderId'], + }, + requiredPermission: 'write', +} export const MoveWorkflow: ToolCatalogEntry = { - id: "move_workflow", - name: "move_workflow", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"folderId":{"type":"string","description":"Target folder ID. Omit or pass empty string to move to workspace root."},"workflowId":{"type":"string","description":"The workflow ID to move."}},"required":["workflowId"]}, - requiredPermission: "write", -}; + id: 'move_workflow', + name: 'move_workflow', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + folderId: { + type: 'string', + description: 'Target folder ID. Omit or pass empty string to move to workspace root.', + }, + workflowId: { type: 'string', description: 'The workflow ID to move.' }, + }, + required: ['workflowId'], + }, + requiredPermission: 'write', +} export const OauthGetAuthLink: ToolCatalogEntry = { - id: "oauth_get_auth_link", - name: "oauth_get_auth_link", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"providerName":{"type":"string","description":"The name of the OAuth provider to connect (e.g., 'Slack', 'Gmail', 'Google Calendar', 'GitHub')"}},"required":["providerName"]}, -}; + id: 'oauth_get_auth_link', + name: 'oauth_get_auth_link', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + providerName: { + type: 'string', + description: + "The name of the OAuth provider to connect (e.g., 'Slack', 'Gmail', 'Google Calendar', 'GitHub')", + }, + }, + required: ['providerName'], + }, +} export const OauthRequestAccess: ToolCatalogEntry = { - id: "oauth_request_access", - name: "oauth_request_access", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"providerName":{"type":"string","description":"The name of the OAuth provider to connect (e.g., 'Slack', 'Gmail', 'Google Calendar')"}},"required":["providerName"]}, + id: 'oauth_request_access', + name: 'oauth_request_access', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + providerName: { + type: 'string', + description: + "The name of the OAuth provider to connect (e.g., 'Slack', 'Gmail', 'Google Calendar')", + }, + }, + required: ['providerName'], + }, requiresConfirmation: true, -}; +} export const OpenResource: ToolCatalogEntry = { - id: "open_resource", - name: "open_resource", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"id":{"type":"string","description":"The resource ID to open."},"type":{"type":"string","description":"The resource type to open.","enum":["workflow","table","knowledgebase","file"]}},"required":["type","id"]}, -}; + id: 'open_resource', + name: 'open_resource', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + id: { type: 'string', description: 'The resource ID to open.' }, + type: { + type: 'string', + description: 'The resource type to open.', + enum: ['workflow', 'table', 'knowledgebase', 'file'], + }, + }, + required: ['type', 'id'], + }, +} export const Read: ToolCatalogEntry = { - id: "read", - name: "read", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"limit":{"type":"number","description":"Maximum number of lines to read."},"offset":{"type":"number","description":"Line offset to start reading from (0-indexed)."},"outputTable":{"type":"string","description":"Table ID to import the file contents into (CSV/JSON). All existing rows are replaced. Example: \"tbl_abc123\""},"path":{"type":"string","description":"Path to the file to read (e.g. 'workflows/My Workflow/state.json')."}},"required":["path"]}, -}; + id: 'read', + name: 'read', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + limit: { type: 'number', description: 'Maximum number of lines to read.' }, + offset: { type: 'number', description: 'Line offset to start reading from (0-indexed).' }, + outputTable: { + type: 'string', + description: + 'Table ID to import the file contents into (CSV/JSON). All existing rows are replaced. Example: "tbl_abc123"', + }, + path: { + type: 'string', + description: "Path to the file to read (e.g. 'workflows/My Workflow/state.json').", + }, + }, + required: ['path'], + }, +} export const Redeploy: ToolCatalogEntry = { - id: "redeploy", - name: "redeploy", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"workflowId":{"type":"string","description":"Workflow ID to redeploy (required in workspace context)"}}}, + id: 'redeploy', + name: 'redeploy', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + workflowId: { + type: 'string', + description: 'Workflow ID to redeploy (required in workspace context)', + }, + }, + }, requiresConfirmation: true, - requiredPermission: "admin", -}; + requiredPermission: 'admin', +} export const RenameWorkflow: ToolCatalogEntry = { - id: "rename_workflow", - name: "rename_workflow", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"name":{"type":"string","description":"The new name for the workflow."},"workflowId":{"type":"string","description":"The workflow ID to rename."}},"required":["workflowId","name"]}, - requiredPermission: "write", -}; + id: 'rename_workflow', + name: 'rename_workflow', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + name: { type: 'string', description: 'The new name for the workflow.' }, + workflowId: { type: 'string', description: 'The workflow ID to rename.' }, + }, + required: ['workflowId', 'name'], + }, + requiredPermission: 'write', +} export const Research: ToolCatalogEntry = { - id: "research", - name: "research", - executor: "subagent", - mode: "async", - parameters: {"properties":{"topic":{"description":"The topic to research.","type":"string"}},"required":["topic"],"type":"object"}, - subagentId: "research", + id: 'research', + name: 'research', + executor: 'subagent', + mode: 'async', + parameters: { + properties: { topic: { description: 'The topic to research.', type: 'string' } }, + required: ['topic'], + type: 'object', + }, + subagentId: 'research', internal: true, -}; +} export const Respond: ToolCatalogEntry = { - id: "respond", - name: "respond", - executor: "sim", - mode: "async", - parameters: {"additionalProperties":true,"properties":{"output":{"description":"The result — facts, status, VFS paths to persisted data, whatever the caller needs to act on.","type":"string"},"success":{"description":"Whether the task completed successfully","type":"boolean"},"type":{"description":"Optional logical result type override","type":"string"}},"required":["output","success"],"type":"object"}, + id: 'respond', + name: 'respond', + executor: 'sim', + mode: 'async', + parameters: { + additionalProperties: true, + properties: { + output: { + description: + 'The result — facts, status, VFS paths to persisted data, whatever the caller needs to act on.', + type: 'string', + }, + success: { description: 'Whether the task completed successfully', type: 'boolean' }, + type: { description: 'Optional logical result type override', type: 'string' }, + }, + required: ['output', 'success'], + type: 'object', + }, internal: true, hidden: true, -}; +} export const RevertToVersion: ToolCatalogEntry = { - id: "revert_to_version", - name: "revert_to_version", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"version":{"type":"number","description":"The deployment version number to revert to"},"workflowId":{"type":"string","description":"The workflow ID"}},"required":["workflowId","version"]}, + id: 'revert_to_version', + name: 'revert_to_version', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + version: { type: 'number', description: 'The deployment version number to revert to' }, + workflowId: { type: 'string', description: 'The workflow ID' }, + }, + required: ['workflowId', 'version'], + }, requiresConfirmation: true, - requiredPermission: "admin", -}; + requiredPermission: 'admin', +} export const Run: ToolCatalogEntry = { - id: "run", - name: "run", - executor: "subagent", - mode: "async", - parameters: {"properties":{"context":{"description":"Pre-gathered context: workflow state, block IDs, input requirements.","type":"string"},"request":{"description":"What to run or what logs to check.","type":"string"}},"required":["request"],"type":"object"}, - subagentId: "run", + id: 'run', + name: 'run', + executor: 'subagent', + mode: 'async', + parameters: { + properties: { + context: { + description: 'Pre-gathered context: workflow state, block IDs, input requirements.', + type: 'string', + }, + request: { description: 'What to run or what logs to check.', type: 'string' }, + }, + required: ['request'], + type: 'object', + }, + subagentId: 'run', internal: true, -}; +} export const RunBlock: ToolCatalogEntry = { - id: "run_block", - name: "run_block", - executor: "client", - mode: "async", - parameters: {"type":"object","properties":{"blockId":{"type":"string","description":"The block ID to run in isolation."},"executionId":{"type":"string","description":"Optional execution ID to load the snapshot from. Uses latest execution if omitted."},"useDeployedState":{"type":"boolean","description":"When true, runs the deployed version instead of the live draft. Default: false (draft)."},"workflowId":{"type":"string","description":"Optional workflow ID to run. If not provided, uses the current workflow in context."},"workflow_input":{"type":"object","description":"JSON object with key-value mappings where each key is an input field name"}},"required":["blockId"]}, + id: 'run_block', + name: 'run_block', + executor: 'client', + mode: 'async', + parameters: { + type: 'object', + properties: { + blockId: { type: 'string', description: 'The block ID to run in isolation.' }, + executionId: { + type: 'string', + description: + 'Optional execution ID to load the snapshot from. Uses latest execution if omitted.', + }, + useDeployedState: { + type: 'boolean', + description: + 'When true, runs the deployed version instead of the live draft. Default: false (draft).', + }, + workflowId: { + type: 'string', + description: + 'Optional workflow ID to run. If not provided, uses the current workflow in context.', + }, + workflow_input: { + type: 'object', + description: 'JSON object with key-value mappings where each key is an input field name', + }, + }, + required: ['blockId'], + }, clientExecutable: true, requiresConfirmation: true, -}; +} export const RunFromBlock: ToolCatalogEntry = { - id: "run_from_block", - name: "run_from_block", - executor: "client", - mode: "async", - parameters: {"type":"object","properties":{"executionId":{"type":"string","description":"Optional execution ID to load the snapshot from. Uses latest execution if omitted."},"startBlockId":{"type":"string","description":"The block ID to start execution from."},"useDeployedState":{"type":"boolean","description":"When true, runs the deployed version instead of the live draft. Default: false (draft)."},"workflowId":{"type":"string","description":"Optional workflow ID to run. If not provided, uses the current workflow in context."},"workflow_input":{"type":"object","description":"JSON object with key-value mappings where each key is an input field name"}},"required":["startBlockId"]}, + id: 'run_from_block', + name: 'run_from_block', + executor: 'client', + mode: 'async', + parameters: { + type: 'object', + properties: { + executionId: { + type: 'string', + description: + 'Optional execution ID to load the snapshot from. Uses latest execution if omitted.', + }, + startBlockId: { type: 'string', description: 'The block ID to start execution from.' }, + useDeployedState: { + type: 'boolean', + description: + 'When true, runs the deployed version instead of the live draft. Default: false (draft).', + }, + workflowId: { + type: 'string', + description: + 'Optional workflow ID to run. If not provided, uses the current workflow in context.', + }, + workflow_input: { + type: 'object', + description: 'JSON object with key-value mappings where each key is an input field name', + }, + }, + required: ['startBlockId'], + }, clientExecutable: true, requiresConfirmation: true, -}; +} export const RunWorkflow: ToolCatalogEntry = { - id: "run_workflow", - name: "run_workflow", - executor: "client", - mode: "async", - parameters: {"type":"object","properties":{"useDeployedState":{"type":"boolean","description":"When true, runs the deployed version instead of the live draft. Default: false (draft)."},"workflowId":{"type":"string","description":"Optional workflow ID to run. If not provided, uses the current workflow in context."},"workflow_input":{"type":"object","description":"JSON object with key-value mappings where each key is an input field name"}},"required":["workflow_input"]}, + id: 'run_workflow', + name: 'run_workflow', + executor: 'client', + mode: 'async', + parameters: { + type: 'object', + properties: { + useDeployedState: { + type: 'boolean', + description: + 'When true, runs the deployed version instead of the live draft. Default: false (draft).', + }, + workflowId: { + type: 'string', + description: + 'Optional workflow ID to run. If not provided, uses the current workflow in context.', + }, + workflow_input: { + type: 'object', + description: 'JSON object with key-value mappings where each key is an input field name', + }, + }, + required: ['workflow_input'], + }, clientExecutable: true, requiresConfirmation: true, -}; +} export const RunWorkflowUntilBlock: ToolCatalogEntry = { - id: "run_workflow_until_block", - name: "run_workflow_until_block", - executor: "client", - mode: "async", - parameters: {"type":"object","properties":{"stopAfterBlockId":{"type":"string","description":"The block ID to stop after. Execution halts once this block completes."},"useDeployedState":{"type":"boolean","description":"When true, runs the deployed version instead of the live draft. Default: false (draft)."},"workflowId":{"type":"string","description":"Optional workflow ID to run. If not provided, uses the current workflow in context."},"workflow_input":{"type":"object","description":"JSON object with key-value mappings where each key is an input field name"}},"required":["stopAfterBlockId"]}, + id: 'run_workflow_until_block', + name: 'run_workflow_until_block', + executor: 'client', + mode: 'async', + parameters: { + type: 'object', + properties: { + stopAfterBlockId: { + type: 'string', + description: 'The block ID to stop after. Execution halts once this block completes.', + }, + useDeployedState: { + type: 'boolean', + description: + 'When true, runs the deployed version instead of the live draft. Default: false (draft).', + }, + workflowId: { + type: 'string', + description: + 'Optional workflow ID to run. If not provided, uses the current workflow in context.', + }, + workflow_input: { + type: 'object', + description: 'JSON object with key-value mappings where each key is an input field name', + }, + }, + required: ['stopAfterBlockId'], + }, clientExecutable: true, requiresConfirmation: true, -}; +} export const ScrapePage: ToolCatalogEntry = { - id: "scrape_page", - name: "scrape_page", - executor: "go", - mode: "sync", - parameters: {"type":"object","properties":{"include_links":{"type":"boolean","description":"Extract all links from the page (default false)"},"url":{"type":"string","description":"The URL to scrape (must include https://)"},"wait_for":{"type":"string","description":"CSS selector to wait for before scraping (for JS-heavy pages)"}},"required":["url"]}, -}; + id: 'scrape_page', + name: 'scrape_page', + executor: 'go', + mode: 'sync', + parameters: { + type: 'object', + properties: { + include_links: { + type: 'boolean', + description: 'Extract all links from the page (default false)', + }, + url: { type: 'string', description: 'The URL to scrape (must include https://)' }, + wait_for: { + type: 'string', + description: 'CSS selector to wait for before scraping (for JS-heavy pages)', + }, + }, + required: ['url'], + }, +} export const SearchDocumentation: ToolCatalogEntry = { - id: "search_documentation", - name: "search_documentation", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"query":{"type":"string","description":"The search query"},"topK":{"type":"number","description":"Number of results (max 10)"}},"required":["query"]}, -}; + id: 'search_documentation', + name: 'search_documentation', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + query: { type: 'string', description: 'The search query' }, + topK: { type: 'number', description: 'Number of results (max 10)' }, + }, + required: ['query'], + }, +} export const SearchLibraryDocs: ToolCatalogEntry = { - id: "search_library_docs", - name: "search_library_docs", - executor: "go", - mode: "sync", - parameters: {"type":"object","properties":{"library_name":{"type":"string","description":"Name of the library to search for (e.g., 'nextjs', 'stripe', 'langchain')"},"query":{"type":"string","description":"The question or topic to find documentation for - be specific"},"version":{"type":"string","description":"Specific version (optional, e.g., '14', 'v2')"}},"required":["library_name","query"]}, -}; + id: 'search_library_docs', + name: 'search_library_docs', + executor: 'go', + mode: 'sync', + parameters: { + type: 'object', + properties: { + library_name: { + type: 'string', + description: "Name of the library to search for (e.g., 'nextjs', 'stripe', 'langchain')", + }, + query: { + type: 'string', + description: 'The question or topic to find documentation for - be specific', + }, + version: { type: 'string', description: "Specific version (optional, e.g., '14', 'v2')" }, + }, + required: ['library_name', 'query'], + }, +} export const SearchOnline: ToolCatalogEntry = { - id: "search_online", - name: "search_online", - executor: "go", - mode: "sync", - parameters: {"type":"object","properties":{"category":{"type":"string","description":"Filter by category","enum":["news","tweet","github","paper","company","research paper","linkedin profile","pdf","personal site"]},"include_text":{"type":"boolean","description":"Include page text content (default true)"},"num_results":{"type":"number","description":"Number of results (default 10, max 25)"},"query":{"type":"string","description":"Natural language search query"}},"required":["query"]}, -}; + id: 'search_online', + name: 'search_online', + executor: 'go', + mode: 'sync', + parameters: { + type: 'object', + properties: { + category: { + type: 'string', + description: 'Filter by category', + enum: [ + 'news', + 'tweet', + 'github', + 'paper', + 'company', + 'research paper', + 'linkedin profile', + 'pdf', + 'personal site', + ], + }, + include_text: { type: 'boolean', description: 'Include page text content (default true)' }, + num_results: { type: 'number', description: 'Number of results (default 10, max 25)' }, + query: { type: 'string', description: 'Natural language search query' }, + }, + required: ['query'], + }, +} export const SearchPatterns: ToolCatalogEntry = { - id: "search_patterns", - name: "search_patterns", - executor: "go", - mode: "sync", - parameters: {"type":"object","properties":{"limit":{"type":"integer","description":"Maximum number of unique pattern examples to return (defaults to 3)."},"queries":{"type":"array","description":"Up to 3 descriptive strings explaining the workflow pattern(s) you need. Focus on intent and desired outcomes.","items":{"type":"string","description":"Example: \"how to automate wealthbox meeting notes into follow-up tasks\""}}},"required":["queries"]}, -}; + id: 'search_patterns', + name: 'search_patterns', + executor: 'go', + mode: 'sync', + parameters: { + type: 'object', + properties: { + limit: { + type: 'integer', + description: 'Maximum number of unique pattern examples to return (defaults to 3).', + }, + queries: { + type: 'array', + description: + 'Up to 3 descriptive strings explaining the workflow pattern(s) you need. Focus on intent and desired outcomes.', + items: { + type: 'string', + description: 'Example: "how to automate wealthbox meeting notes into follow-up tasks"', + }, + }, + }, + required: ['queries'], + }, +} export const SetEnvironmentVariables: ToolCatalogEntry = { - id: "set_environment_variables", - name: "set_environment_variables", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"variables":{"type":"array","description":"List of env vars to set","items":{"type":"object","properties":{"name":{"type":"string","description":"Variable name"},"value":{"type":"string","description":"Variable value"}},"required":["name","value"]}}},"required":["variables"]}, + id: 'set_environment_variables', + name: 'set_environment_variables', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + variables: { + type: 'array', + description: 'List of env vars to set', + items: { + type: 'object', + properties: { + name: { type: 'string', description: 'Variable name' }, + value: { type: 'string', description: 'Variable value' }, + }, + required: ['name', 'value'], + }, + }, + }, + required: ['variables'], + }, requiresConfirmation: true, - requiredPermission: "write", -}; + requiredPermission: 'write', +} export const SetGlobalWorkflowVariables: ToolCatalogEntry = { - id: "set_global_workflow_variables", - name: "set_global_workflow_variables", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"operations":{"type":"array","description":"List of operations to apply","items":{"type":"object","properties":{"name":{"type":"string"},"operation":{"type":"string","enum":["add","delete","edit"]},"type":{"type":"string","enum":["plain","number","boolean","array","object"]},"value":{"type":"string"}},"required":["operation","name","type","value"]}},"workflowId":{"type":"string","description":"Optional workflow ID. If not provided, uses the current workflow in context."}},"required":["operations"]}, + id: 'set_global_workflow_variables', + name: 'set_global_workflow_variables', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + operations: { + type: 'array', + description: 'List of operations to apply', + items: { + type: 'object', + properties: { + name: { type: 'string' }, + operation: { type: 'string', enum: ['add', 'delete', 'edit'] }, + type: { type: 'string', enum: ['plain', 'number', 'boolean', 'array', 'object'] }, + value: { type: 'string' }, + }, + required: ['operation', 'name', 'type', 'value'], + }, + }, + workflowId: { + type: 'string', + description: 'Optional workflow ID. If not provided, uses the current workflow in context.', + }, + }, + required: ['operations'], + }, requiresConfirmation: true, - requiredPermission: "write", -}; + requiredPermission: 'write', +} export const Superagent: ToolCatalogEntry = { - id: "superagent", - name: "superagent", - executor: "subagent", - mode: "async", - parameters: {"properties":{"task":{"description":"A single sentence — the agent has full conversation context. Do NOT pre-read credentials or look up configs. Example: 'send the email we discussed' or 'check my calendar for tomorrow'.","type":"string"}},"required":["task"],"type":"object"}, - subagentId: "superagent", + id: 'superagent', + name: 'superagent', + executor: 'subagent', + mode: 'async', + parameters: { + properties: { + task: { + description: + "A single sentence — the agent has full conversation context. Do NOT pre-read credentials or look up configs. Example: 'send the email we discussed' or 'check my calendar for tomorrow'.", + type: 'string', + }, + }, + required: ['task'], + type: 'object', + }, + subagentId: 'superagent', internal: true, -}; +} export const Table: ToolCatalogEntry = { - id: "table", - name: "table", - executor: "subagent", - mode: "async", - parameters: {"properties":{"request":{"description":"What table action is needed.","type":"string"}},"required":["request"],"type":"object"}, - subagentId: "table", + id: 'table', + name: 'table', + executor: 'subagent', + mode: 'async', + parameters: { + properties: { request: { description: 'What table action is needed.', type: 'string' } }, + required: ['request'], + type: 'object', + }, + subagentId: 'table', internal: true, -}; +} export const ToolSearchToolRegex: ToolCatalogEntry = { - id: "tool_search_tool_regex", - name: "tool_search_tool_regex", - executor: "sim", - mode: "async", - parameters: {"properties":{"case_insensitive":{"description":"Whether the regex should be case-insensitive (default true).","type":"boolean"},"max_results":{"description":"Maximum number of tools to return (optional).","type":"integer"},"pattern":{"description":"Regular expression to match tool names or descriptions.","type":"string"}},"required":["pattern"],"type":"object"}, -}; + id: 'tool_search_tool_regex', + name: 'tool_search_tool_regex', + executor: 'sim', + mode: 'async', + parameters: { + properties: { + case_insensitive: { + description: 'Whether the regex should be case-insensitive (default true).', + type: 'boolean', + }, + max_results: { + description: 'Maximum number of tools to return (optional).', + type: 'integer', + }, + pattern: { + description: 'Regular expression to match tool names or descriptions.', + type: 'string', + }, + }, + required: ['pattern'], + type: 'object', + }, +} export const UpdateJobHistory: ToolCatalogEntry = { - id: "update_job_history", - name: "update_job_history", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"jobId":{"type":"string","description":"The job ID."},"summary":{"type":"string","description":"A concise summary of what was done this run (e.g., 'Sent follow-up emails to 3 leads: Alice, Bob, Carol')."}},"required":["jobId","summary"]}, -}; + id: 'update_job_history', + name: 'update_job_history', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + jobId: { type: 'string', description: 'The job ID.' }, + summary: { + type: 'string', + description: + "A concise summary of what was done this run (e.g., 'Sent follow-up emails to 3 leads: Alice, Bob, Carol').", + }, + }, + required: ['jobId', 'summary'], + }, +} export const UpdateWorkspaceMcpServer: ToolCatalogEntry = { - id: "update_workspace_mcp_server", - name: "update_workspace_mcp_server", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"description":{"type":"string","description":"New description for the server"},"isPublic":{"type":"boolean","description":"Whether the server is publicly accessible"},"name":{"type":"string","description":"New name for the server"},"serverId":{"type":"string","description":"Required: the MCP server ID to update"}},"required":["serverId"]}, + id: 'update_workspace_mcp_server', + name: 'update_workspace_mcp_server', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + description: { type: 'string', description: 'New description for the server' }, + isPublic: { type: 'boolean', description: 'Whether the server is publicly accessible' }, + name: { type: 'string', description: 'New name for the server' }, + serverId: { type: 'string', description: 'Required: the MCP server ID to update' }, + }, + required: ['serverId'], + }, requiresConfirmation: true, - requiredPermission: "admin", -}; + requiredPermission: 'admin', +} export const UserMemory: ToolCatalogEntry = { - id: "user_memory", - name: "user_memory", - executor: "go", - mode: "sync", - parameters: {"type":"object","properties":{"confidence":{"type":"number","description":"Confidence level 0-1 (default 1.0 for explicit, 0.8 for inferred)"},"correct_value":{"type":"string","description":"The correct value to replace the wrong one (for 'correct' operation)"},"key":{"type":"string","description":"Unique key for the memory (e.g., 'preferred_model', 'slack_credential')"},"limit":{"type":"number","description":"Number of results for search (default 10)"},"memory_type":{"type":"string","description":"Type of memory: 'preference', 'entity', 'history', or 'correction'","enum":["preference","entity","history","correction"]},"operation":{"type":"string","description":"Operation: 'add', 'search', 'delete', 'correct', or 'list'","enum":["add","search","delete","correct","list"]},"query":{"type":"string","description":"Search query to find relevant memories"},"source":{"type":"string","description":"Source: 'explicit' (user told you) or 'inferred' (you observed)","enum":["explicit","inferred"]},"value":{"type":"string","description":"Value to remember"}},"required":["operation"]}, -}; + id: 'user_memory', + name: 'user_memory', + executor: 'go', + mode: 'sync', + parameters: { + type: 'object', + properties: { + confidence: { + type: 'number', + description: 'Confidence level 0-1 (default 1.0 for explicit, 0.8 for inferred)', + }, + correct_value: { + type: 'string', + description: "The correct value to replace the wrong one (for 'correct' operation)", + }, + key: { + type: 'string', + description: "Unique key for the memory (e.g., 'preferred_model', 'slack_credential')", + }, + limit: { type: 'number', description: 'Number of results for search (default 10)' }, + memory_type: { + type: 'string', + description: "Type of memory: 'preference', 'entity', 'history', or 'correction'", + enum: ['preference', 'entity', 'history', 'correction'], + }, + operation: { + type: 'string', + description: "Operation: 'add', 'search', 'delete', 'correct', or 'list'", + enum: ['add', 'search', 'delete', 'correct', 'list'], + }, + query: { type: 'string', description: 'Search query to find relevant memories' }, + source: { + type: 'string', + description: "Source: 'explicit' (user told you) or 'inferred' (you observed)", + enum: ['explicit', 'inferred'], + }, + value: { type: 'string', description: 'Value to remember' }, + }, + required: ['operation'], + }, +} export const UserTable: ToolCatalogEntry = { - id: "user_table", - name: "user_table", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"args":{"type":"object","description":"Arguments for the operation","properties":{"column":{"type":"object","description":"Column definition for add_column: { name, type, unique?, position? }"},"columnName":{"type":"string","description":"Column name (required for rename_column, update_column; use columnNames array for batch delete_column)"},"columnNames":{"type":"array","description":"Array of column names to delete at once (for delete_column). Preferred over columnName when deleting multiple columns."},"data":{"type":"object","description":"Row data as key-value pairs (required for insert_row, update_row)"},"description":{"type":"string","description":"Table description (optional for 'create')"},"fileId":{"type":"string","description":"Canonical workspace file ID for create_from_file/import_file. Discover via read(\"files/{name}/meta.json\") or glob(\"files/by-id/*/meta.json\")."},"filePath":{"type":"string","description":"Legacy workspace file reference for create_from_file/import_file. Prefer fileId."},"filter":{"type":"object","description":"MongoDB-style filter for query_rows, update_rows_by_filter, delete_rows_by_filter"},"limit":{"type":"number","description":"Maximum rows to return or affect (optional, default 100)"},"name":{"type":"string","description":"Table name (required for 'create')"},"newName":{"type":"string","description":"New column name (required for rename_column)"},"newType":{"type":"string","description":"New column type (optional for update_column). Types: string, number, boolean, date, json"},"offset":{"type":"number","description":"Number of rows to skip (optional for query_rows, default 0)"},"outputFormat":{"type":"string","description":"Explicit format override for outputPath. Usually unnecessary — the file extension determines the format automatically. Only use this to force a different format than what the extension implies.","enum":["json","csv","txt","md","html"]},"outputPath":{"type":"string","description":"Pipe query_rows results directly to a NEW workspace file. The format is auto-inferred from the file extension: .csv → CSV, .json → JSON, .md → Markdown, etc. Use .csv for tabular exports. Use a flat path like \"files/export.csv\" — nested paths are not supported."},"rowId":{"type":"string","description":"Row ID (required for get_row, update_row, delete_row)"},"rowIds":{"type":"array","description":"Array of row IDs to delete (for batch_delete_rows)"},"rows":{"type":"array","description":"Array of row data objects (required for batch_insert_rows)"},"schema":{"type":"object","description":"Table schema with columns array (required for 'create'). Each column: { name, type, unique? }"},"sort":{"type":"object","description":"Sort specification as { field: 'asc' | 'desc' } (optional for query_rows)"},"tableId":{"type":"string","description":"Table ID (required for most operations except 'create')"},"unique":{"type":"boolean","description":"Set column unique constraint (optional for update_column)"},"updates":{"type":"array","description":"Array of per-row updates: [{ rowId, data: { col: val } }] (for batch_update_rows)"},"values":{"type":"object","description":"Map of rowId to value for single-column batch update: { \"rowId1\": val1, \"rowId2\": val2 } (for batch_update_rows with columnName)"}}},"operation":{"type":"string","description":"The operation to perform","enum":["create","create_from_file","import_file","get","get_schema","delete","insert_row","batch_insert_rows","get_row","query_rows","update_row","delete_row","update_rows_by_filter","delete_rows_by_filter","batch_update_rows","batch_delete_rows","add_column","rename_column","delete_column","update_column"]}},"required":["operation","args"]}, - resultSchema: {"type":"object","properties":{"data":{"type":"object","description":"Operation-specific result payload."},"message":{"type":"string","description":"Human-readable outcome summary."},"success":{"type":"boolean","description":"Whether the operation succeeded."}},"required":["success","message"]}, + id: 'user_table', + name: 'user_table', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + args: { + type: 'object', + description: 'Arguments for the operation', + properties: { + column: { + type: 'object', + description: 'Column definition for add_column: { name, type, unique?, position? }', + }, + columnName: { + type: 'string', + description: + 'Column name (required for rename_column, update_column; use columnNames array for batch delete_column)', + }, + columnNames: { + type: 'array', + description: + 'Array of column names to delete at once (for delete_column). Preferred over columnName when deleting multiple columns.', + }, + data: { + type: 'object', + description: 'Row data as key-value pairs (required for insert_row, update_row)', + }, + description: { type: 'string', description: "Table description (optional for 'create')" }, + fileId: { + type: 'string', + description: + 'Canonical workspace file ID for create_from_file/import_file. Discover via read("files/{name}/meta.json") or glob("files/by-id/*/meta.json").', + }, + filePath: { + type: 'string', + description: + 'Legacy workspace file reference for create_from_file/import_file. Prefer fileId.', + }, + filter: { + type: 'object', + description: + 'MongoDB-style filter for query_rows, update_rows_by_filter, delete_rows_by_filter', + }, + limit: { + type: 'number', + description: 'Maximum rows to return or affect (optional, default 100)', + }, + name: { type: 'string', description: "Table name (required for 'create')" }, + newName: { type: 'string', description: 'New column name (required for rename_column)' }, + newType: { + type: 'string', + description: + 'New column type (optional for update_column). Types: string, number, boolean, date, json', + }, + offset: { + type: 'number', + description: 'Number of rows to skip (optional for query_rows, default 0)', + }, + outputFormat: { + type: 'string', + description: + 'Explicit format override for outputPath. Usually unnecessary — the file extension determines the format automatically. Only use this to force a different format than what the extension implies.', + enum: ['json', 'csv', 'txt', 'md', 'html'], + }, + outputPath: { + type: 'string', + description: + 'Pipe query_rows results directly to a NEW workspace file. The format is auto-inferred from the file extension: .csv → CSV, .json → JSON, .md → Markdown, etc. Use .csv for tabular exports. Use a flat path like "files/export.csv" — nested paths are not supported.', + }, + rowId: { + type: 'string', + description: 'Row ID (required for get_row, update_row, delete_row)', + }, + rowIds: { + type: 'array', + description: 'Array of row IDs to delete (for batch_delete_rows)', + }, + rows: { + type: 'array', + description: 'Array of row data objects (required for batch_insert_rows)', + }, + schema: { + type: 'object', + description: + "Table schema with columns array (required for 'create'). Each column: { name, type, unique? }", + }, + sort: { + type: 'object', + description: + "Sort specification as { field: 'asc' | 'desc' } (optional for query_rows)", + }, + tableId: { + type: 'string', + description: "Table ID (required for most operations except 'create')", + }, + unique: { + type: 'boolean', + description: 'Set column unique constraint (optional for update_column)', + }, + updates: { + type: 'array', + description: + 'Array of per-row updates: [{ rowId, data: { col: val } }] (for batch_update_rows)', + }, + values: { + type: 'object', + description: + 'Map of rowId to value for single-column batch update: { "rowId1": val1, "rowId2": val2 } (for batch_update_rows with columnName)', + }, + }, + }, + operation: { + type: 'string', + description: 'The operation to perform', + enum: [ + 'create', + 'create_from_file', + 'import_file', + 'get', + 'get_schema', + 'delete', + 'insert_row', + 'batch_insert_rows', + 'get_row', + 'query_rows', + 'update_row', + 'delete_row', + 'update_rows_by_filter', + 'delete_rows_by_filter', + 'batch_update_rows', + 'batch_delete_rows', + 'add_column', + 'rename_column', + 'delete_column', + 'update_column', + ], + }, + }, + required: ['operation', 'args'], + }, + resultSchema: { + type: 'object', + properties: { + data: { type: 'object', description: 'Operation-specific result payload.' }, + message: { type: 'string', description: 'Human-readable outcome summary.' }, + success: { type: 'boolean', description: 'Whether the operation succeeded.' }, + }, + required: ['success', 'message'], + }, requiresConfirmation: true, -}; +} export const Workflow: ToolCatalogEntry = { - id: "workflow", - name: "workflow", - executor: "subagent", - mode: "async", - parameters: {"properties":{"request":{"description":"A single sentence — the agent has full conversation context and VFS access. Do NOT look up IDs or pre-read data; the workflow agent does its own research. Example: 'move all the return letter workflows into a folder called Letters'.","type":"string"}},"required":["request"],"type":"object"}, - subagentId: "workflow", + id: 'workflow', + name: 'workflow', + executor: 'subagent', + mode: 'async', + parameters: { + properties: { + request: { + description: + "A single sentence — the agent has full conversation context and VFS access. Do NOT look up IDs or pre-read data; the workflow agent does its own research. Example: 'move all the return letter workflows into a folder called Letters'.", + type: 'string', + }, + }, + required: ['request'], + type: 'object', + }, + subagentId: 'workflow', internal: true, -}; +} export const WorkspaceFile: ToolCatalogEntry = { - id: "workspace_file", - name: "workspace_file", - executor: "sim", - mode: "async", - parameters: {"type":"object","properties":{"operation":{"type":"string","description":"The file operation to perform.","enum":["create","append","update","patch","rename","delete"]},"target":{"type":"object","description":"Explicit file target. Use kind=new_file + fileName for create. Use kind=file_id + fileId for append, update, patch, rename, and delete. Emit target keys in this order: kind, fileId, fileName.","properties":{"kind":{"type":"string","description":"How the file target is identified.","enum":["new_file","file_id"]},"fileId":{"type":"string","description":"Canonical existing workspace file ID. Required when target.kind=file_id."},"fileName":{"type":"string","description":"Plain workspace filename including extension, e.g. \"main.py\" or \"report.docx\". Required when target.kind=new_file."}},"required":["kind"]},"title":{"type":"string","description":"Optional short UI label for create/append chunks, e.g. \"Chapter 1\" or \"Slide 3\"."},"contentType":{"type":"string","description":"Optional MIME type override. Usually omit and let the system infer from the target file extension.","enum":["text/markdown","text/html","text/plain","application/json","text/csv","application/vnd.openxmlformats-officedocument.presentationml.presentation","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/pdf"]},"edit":{"type":"object","description":"Patch metadata. Use strategy=search_replace for exact text replacement, or strategy=anchored for line-based inserts/replacements/deletions. Emit edit keys in this order: strategy, search, replace, replaceAll, mode, occurrence, before_anchor, after_anchor, anchor, start_anchor, end_anchor, content.","properties":{"strategy":{"type":"string","description":"Patch strategy.","enum":["search_replace","anchored"]},"search":{"type":"string","description":"Exact text to find when strategy=search_replace. Must match exactly once unless replaceAll=true."},"replace":{"type":"string","description":"Replacement text when strategy=search_replace."},"replaceAll":{"type":"boolean","description":"When true and strategy=search_replace, replace every match instead of requiring a unique single match."},"mode":{"type":"string","description":"Anchored edit mode when strategy=anchored.","enum":["replace_between","insert_after","delete_between"]},"occurrence":{"type":"number","description":"1-based occurrence for repeated anchor lines. Optional; defaults to 1."},"before_anchor":{"type":"string","description":"Boundary line kept before inserted replacement content. Required for mode=replace_between."},"after_anchor":{"type":"string","description":"Boundary line kept after inserted replacement content. Required for mode=replace_between."},"anchor":{"type":"string","description":"Anchor line after which new content is inserted. Required for mode=insert_after."},"start_anchor":{"type":"string","description":"First line to delete. Required for mode=delete_between."},"end_anchor":{"type":"string","description":"First line to keep after deletion. Required for mode=delete_between."},"content":{"type":"string","description":"Inserted or replacement content for anchored edits. Not used for delete_between."}}},"newName":{"type":"string","description":"New file name for rename. Must be a plain workspace filename like \"main.py\"."},"content":{"type":"string","description":"File content for create, append, or update. For .pptx/.docx/.pdf this must be JavaScript source code for the corresponding generator runtime."}},"required":["operation","target"]}, - resultSchema: {"type":"object","properties":{"data":{"type":"object","description":"Optional operation metadata such as file id, file name, size, and content type."},"message":{"type":"string","description":"Human-readable summary of the outcome."},"success":{"type":"boolean","description":"Whether the file operation succeeded."}},"required":["success","message"]}, - requiredPermission: "write", -}; + id: 'workspace_file', + name: 'workspace_file', + executor: 'sim', + mode: 'async', + parameters: { + type: 'object', + properties: { + operation: { + type: 'string', + description: 'The file operation to perform.', + enum: ['create', 'append', 'update', 'patch', 'rename', 'delete'], + }, + target: { + type: 'object', + description: + 'Explicit file target. Use kind=new_file + fileName for create. Use kind=file_id + fileId for append, update, patch, rename, and delete. Emit target keys in this order: kind, fileId, fileName.', + properties: { + kind: { + type: 'string', + description: 'How the file target is identified.', + enum: ['new_file', 'file_id'], + }, + fileId: { + type: 'string', + description: 'Canonical existing workspace file ID. Required when target.kind=file_id.', + }, + fileName: { + type: 'string', + description: + 'Plain workspace filename including extension, e.g. "main.py" or "report.docx". Required when target.kind=new_file.', + }, + }, + required: ['kind'], + }, + title: { + type: 'string', + description: + 'Optional short UI label for create/append chunks, e.g. "Chapter 1" or "Slide 3".', + }, + contentType: { + type: 'string', + description: + 'Optional MIME type override. Usually omit and let the system infer from the target file extension.', + enum: [ + 'text/markdown', + 'text/html', + 'text/plain', + 'application/json', + 'text/csv', + 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'application/pdf', + ], + }, + edit: { + type: 'object', + description: + 'Patch metadata. Use strategy=search_replace for exact text replacement, or strategy=anchored for line-based inserts/replacements/deletions. Emit edit keys in this order: strategy, search, replace, replaceAll, mode, occurrence, before_anchor, after_anchor, anchor, start_anchor, end_anchor, content.', + properties: { + strategy: { + type: 'string', + description: 'Patch strategy.', + enum: ['search_replace', 'anchored'], + }, + search: { + type: 'string', + description: + 'Exact text to find when strategy=search_replace. Must match exactly once unless replaceAll=true.', + }, + replace: { + type: 'string', + description: 'Replacement text when strategy=search_replace.', + }, + replaceAll: { + type: 'boolean', + description: + 'When true and strategy=search_replace, replace every match instead of requiring a unique single match.', + }, + mode: { + type: 'string', + description: 'Anchored edit mode when strategy=anchored.', + enum: ['replace_between', 'insert_after', 'delete_between'], + }, + occurrence: { + type: 'number', + description: '1-based occurrence for repeated anchor lines. Optional; defaults to 1.', + }, + before_anchor: { + type: 'string', + description: + 'Boundary line kept before inserted replacement content. Required for mode=replace_between.', + }, + after_anchor: { + type: 'string', + description: + 'Boundary line kept after inserted replacement content. Required for mode=replace_between.', + }, + anchor: { + type: 'string', + description: + 'Anchor line after which new content is inserted. Required for mode=insert_after.', + }, + start_anchor: { + type: 'string', + description: 'First line to delete. Required for mode=delete_between.', + }, + end_anchor: { + type: 'string', + description: 'First line to keep after deletion. Required for mode=delete_between.', + }, + content: { + type: 'string', + description: + 'Inserted or replacement content for anchored edits. Not used for delete_between.', + }, + }, + }, + newName: { + type: 'string', + description: 'New file name for rename. Must be a plain workspace filename like "main.py".', + }, + content: { + type: 'string', + description: + 'File content for create, append, or update. For .pptx/.docx/.pdf this must be JavaScript source code for the corresponding generator runtime.', + }, + }, + required: ['operation', 'target'], + }, + resultSchema: { + type: 'object', + properties: { + data: { + type: 'object', + description: + 'Optional operation metadata such as file id, file name, size, and content type.', + }, + message: { type: 'string', description: 'Human-readable summary of the outcome.' }, + success: { type: 'boolean', description: 'Whether the file operation succeeded.' }, + }, + required: ['success', 'message'], + }, + requiredPermission: 'write', +} export const TOOL_CATALOG: Record = { [Agent.id]: Agent, @@ -833,4 +2701,4 @@ export const TOOL_CATALOG: Record = { [UserTable.id]: UserTable, [Workflow.id]: Workflow, [WorkspaceFile.id]: WorkspaceFile, -}; +} diff --git a/apps/sim/lib/copilot/generated/tool-schemas-v1.ts b/apps/sim/lib/copilot/generated/tool-schemas-v1.ts index c4b5e27484..904ba5811e 100644 --- a/apps/sim/lib/copilot/generated/tool-schemas-v1.ts +++ b/apps/sim/lib/copilot/generated/tool-schemas-v1.ts @@ -5,2601 +5,2388 @@ export type JsonSchema = unknown export interface ToolRuntimeSchemaEntry { - parameters?: JsonSchema; - resultSchema?: JsonSchema; + parameters?: JsonSchema + resultSchema?: JsonSchema } export const TOOL_RUNTIME_SCHEMAS: Record = { - ["agent"]: { + agent: { parameters: { - "properties": { - "request": { - "description": "What tool/skill/MCP action is needed.", - "type": "string" - } + properties: { + request: { + description: 'What tool/skill/MCP action is needed.', + type: 'string', + }, }, - "required": [ - "request" - ], - "type": "object" + required: ['request'], + type: 'object', }, resultSchema: undefined, }, - ["auth"]: { + auth: { parameters: { - "properties": { - "request": { - "description": "What authentication/credential action is needed.", - "type": "string" - } + properties: { + request: { + description: 'What authentication/credential action is needed.', + type: 'string', + }, }, - "required": [ - "request" - ], - "type": "object" + required: ['request'], + type: 'object', }, resultSchema: undefined, }, - ["check_deployment_status"]: { + check_deployment_status: { parameters: { - "type": "object", - "properties": { - "workflowId": { - "type": "string", - "description": "Workflow ID to check (defaults to current workflow)" - } - } - }, - resultSchema: undefined, - }, - ["complete_job"]: { - parameters: { - "type": "object", - "properties": { - "jobId": { - "type": "string", - "description": "The ID of the job to mark as completed." - } + type: 'object', + properties: { + workflowId: { + type: 'string', + description: 'Workflow ID to check (defaults to current workflow)', + }, }, - "required": [ - "jobId" - ] }, resultSchema: undefined, }, - ["context_write"]: { + complete_job: { parameters: { - "type": "object", - "properties": { - "content": { - "type": "string", - "description": "Full content to write to the file (replaces existing content)" + type: 'object', + properties: { + jobId: { + type: 'string', + description: 'The ID of the job to mark as completed.', }, - "file_path": { - "type": "string", - "description": "Path of the file to write (e.g. 'SESSION.md')" - } }, - "required": [ - "file_path", - "content" - ] + required: ['jobId'], }, resultSchema: undefined, }, - ["crawl_website"]: { + context_write: { parameters: { - "type": "object", - "properties": { - "exclude_paths": { - "type": "array", - "description": "Skip URLs matching these patterns", - "items": { - "type": "string" - } + type: 'object', + properties: { + content: { + type: 'string', + description: 'Full content to write to the file (replaces existing content)', }, - "include_paths": { - "type": "array", - "description": "Only crawl URLs matching these patterns", - "items": { - "type": "string" - } + file_path: { + type: 'string', + description: "Path of the file to write (e.g. 'SESSION.md')", }, - "limit": { - "type": "number", - "description": "Maximum pages to crawl (default 10, max 50)" - }, - "max_depth": { - "type": "number", - "description": "How deep to follow links (default 2)" - }, - "url": { - "type": "string", - "description": "Starting URL to crawl from" - } }, - "required": [ - "url" - ] + required: ['file_path', 'content'], }, resultSchema: undefined, }, - ["create_folder"]: { + crawl_website: { parameters: { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Folder name." + type: 'object', + properties: { + exclude_paths: { + type: 'array', + description: 'Skip URLs matching these patterns', + items: { + type: 'string', + }, }, - "parentId": { - "type": "string", - "description": "Optional parent folder ID." + include_paths: { + type: 'array', + description: 'Only crawl URLs matching these patterns', + items: { + type: 'string', + }, + }, + limit: { + type: 'number', + description: 'Maximum pages to crawl (default 10, max 50)', + }, + max_depth: { + type: 'number', + description: 'How deep to follow links (default 2)', + }, + url: { + type: 'string', + description: 'Starting URL to crawl from', }, - "workspaceId": { - "type": "string", - "description": "Optional workspace ID." - } }, - "required": [ - "name" - ] + required: ['url'], }, resultSchema: undefined, }, - ["create_job"]: { + create_folder: { parameters: { - "type": "object", - "properties": { - "cron": { - "type": "string", - "description": "Cron expression for recurring jobs (e.g., '*/5 * * * *' for every 5 minutes, '0 9 * * *' for daily at 9 AM). Omit for one-time jobs." + type: 'object', + properties: { + name: { + type: 'string', + description: 'Folder name.', }, - "lifecycle": { - "type": "string", - "description": "'persistent' (default) or 'until_complete'. Until_complete jobs stop when complete_job is called after the success condition is met.", - "enum": [ - "persistent", - "until_complete" - ] + parentId: { + type: 'string', + description: 'Optional parent folder ID.', }, - "maxRuns": { - "type": "integer", - "description": "Maximum number of executions before the job auto-completes. Safety limit to prevent runaway polling." + workspaceId: { + type: 'string', + description: 'Optional workspace ID.', }, - "prompt": { - "type": "string", - "description": "The prompt to execute when the job fires. This is sent to the Mothership as a user message." - }, - "successCondition": { - "type": "string", - "description": "What must happen for the job to be considered complete. Used with until_complete lifecycle (e.g., 'John has replied to the partnership email')." - }, - "time": { - "type": "string", - "description": "ISO 8601 datetime for one-time execution or as the start time for a cron schedule (e.g., '2026-03-06T09:00:00'). Include timezone offset or use the timezone parameter." - }, - "timezone": { - "type": "string", - "description": "IANA timezone for the schedule (e.g., 'America/New_York', 'Europe/London'). Defaults to UTC." - }, - "title": { - "type": "string", - "description": "A short, descriptive title for the job (e.g., 'Email Poller', 'Daily Report'). Used as the display name." - } }, - "required": [ - "title", - "prompt" - ] + required: ['name'], }, resultSchema: undefined, }, - ["create_workflow"]: { + create_job: { parameters: { - "type": "object", - "properties": { - "description": { - "type": "string", - "description": "Optional workflow description." + type: 'object', + properties: { + cron: { + type: 'string', + description: + "Cron expression for recurring jobs (e.g., '*/5 * * * *' for every 5 minutes, '0 9 * * *' for daily at 9 AM). Omit for one-time jobs.", }, - "folderId": { - "type": "string", - "description": "Optional folder ID." + lifecycle: { + type: 'string', + description: + "'persistent' (default) or 'until_complete'. Until_complete jobs stop when complete_job is called after the success condition is met.", + enum: ['persistent', 'until_complete'], }, - "name": { - "type": "string", - "description": "Workflow name." + maxRuns: { + type: 'integer', + description: + 'Maximum number of executions before the job auto-completes. Safety limit to prevent runaway polling.', + }, + prompt: { + type: 'string', + description: + 'The prompt to execute when the job fires. This is sent to the Mothership as a user message.', + }, + successCondition: { + type: 'string', + description: + "What must happen for the job to be considered complete. Used with until_complete lifecycle (e.g., 'John has replied to the partnership email').", + }, + time: { + type: 'string', + description: + "ISO 8601 datetime for one-time execution or as the start time for a cron schedule (e.g., '2026-03-06T09:00:00'). Include timezone offset or use the timezone parameter.", + }, + timezone: { + type: 'string', + description: + "IANA timezone for the schedule (e.g., 'America/New_York', 'Europe/London'). Defaults to UTC.", + }, + title: { + type: 'string', + description: + "A short, descriptive title for the job (e.g., 'Email Poller', 'Daily Report'). Used as the display name.", }, - "workspaceId": { - "type": "string", - "description": "Optional workspace ID." - } }, - "required": [ - "name" - ] + required: ['title', 'prompt'], }, resultSchema: undefined, }, - ["create_workspace_mcp_server"]: { + create_workflow: { parameters: { - "type": "object", - "properties": { - "description": { - "type": "string", - "description": "Optional description for the server" + type: 'object', + properties: { + description: { + type: 'string', + description: 'Optional workflow description.', }, - "name": { - "type": "string", - "description": "Required: server name" + folderId: { + type: 'string', + description: 'Optional folder ID.', + }, + name: { + type: 'string', + description: 'Workflow name.', + }, + workspaceId: { + type: 'string', + description: 'Optional workspace ID.', }, - "workspaceId": { - "type": "string", - "description": "Workspace ID (defaults to current workspace)" - } }, - "required": [ - "name" - ] + required: ['name'], }, resultSchema: undefined, }, - ["debug"]: { + create_workspace_mcp_server: { parameters: { - "properties": { - "context": { - "description": "Pre-gathered context: workflow state JSON, block schemas, error logs. The debug agent will skip re-reading anything included here.", - "type": "string" + type: 'object', + properties: { + description: { + type: 'string', + description: 'Optional description for the server', + }, + name: { + type: 'string', + description: 'Required: server name', + }, + workspaceId: { + type: 'string', + description: 'Workspace ID (defaults to current workspace)', }, - "request": { - "description": "What to debug. Include error messages, block IDs, and any context about the failure.", - "type": "string" - } }, - "required": [ - "request" - ], - "type": "object" + required: ['name'], }, resultSchema: undefined, }, - ["delete_folder"]: { + debug: { parameters: { - "type": "object", - "properties": { - "folderId": { - "type": "string", - "description": "The folder ID to delete." - } + properties: { + context: { + description: + 'Pre-gathered context: workflow state JSON, block schemas, error logs. The debug agent will skip re-reading anything included here.', + type: 'string', + }, + request: { + description: + 'What to debug. Include error messages, block IDs, and any context about the failure.', + type: 'string', + }, }, - "required": [ - "folderId" - ] + required: ['request'], + type: 'object', }, resultSchema: undefined, }, - ["delete_workflow"]: { + delete_folder: { parameters: { - "type": "object", - "properties": { - "workflowId": { - "type": "string", - "description": "The workflow ID to delete." - } + type: 'object', + properties: { + folderId: { + type: 'string', + description: 'The folder ID to delete.', + }, }, - "required": [ - "workflowId" - ] + required: ['folderId'], }, resultSchema: undefined, }, - ["delete_workspace_mcp_server"]: { + delete_workflow: { parameters: { - "type": "object", - "properties": { - "serverId": { - "type": "string", - "description": "Required: the MCP server ID to delete" - } + type: 'object', + properties: { + workflowId: { + type: 'string', + description: 'The workflow ID to delete.', + }, }, - "required": [ - "serverId" - ] + required: ['workflowId'], }, resultSchema: undefined, }, - ["deploy"]: { + delete_workspace_mcp_server: { parameters: { - "properties": { - "request": { - "description": "Detailed deployment instructions. Include deployment type (api/chat) and ALL user-specified options: identifier, title, description, authType, password, allowedEmails, welcomeMessage, outputConfigs (block outputs to display).", - "type": "string" - } + type: 'object', + properties: { + serverId: { + type: 'string', + description: 'Required: the MCP server ID to delete', + }, }, - "required": [ - "request" - ], - "type": "object" + required: ['serverId'], }, resultSchema: undefined, }, - ["deploy_api"]: { + deploy: { parameters: { - "type": "object", - "properties": { - "action": { - "type": "string", - "description": "Whether to deploy or undeploy the API endpoint", - "enum": [ - "deploy", - "undeploy" - ], - "default": "deploy" + properties: { + request: { + description: + 'Detailed deployment instructions. Include deployment type (api/chat) and ALL user-specified options: identifier, title, description, authType, password, allowedEmails, welcomeMessage, outputConfigs (block outputs to display).', + type: 'string', }, - "workflowId": { - "type": "string", - "description": "Workflow ID to deploy (required in workspace context)" - } - } + }, + required: ['request'], + type: 'object', }, resultSchema: undefined, }, - ["deploy_chat"]: { + deploy_api: { parameters: { - "type": "object", - "properties": { - "action": { - "type": "string", - "description": "Whether to deploy or undeploy the chat interface", - "enum": [ - "deploy", - "undeploy" - ], - "default": "deploy" + type: 'object', + properties: { + action: { + type: 'string', + description: 'Whether to deploy or undeploy the API endpoint', + enum: ['deploy', 'undeploy'], + default: 'deploy', }, - "allowedEmails": { - "type": "array", - "description": "List of allowed emails/domains for email or SSO auth", - "items": { - "type": "string" - } + workflowId: { + type: 'string', + description: 'Workflow ID to deploy (required in workspace context)', }, - "authType": { - "type": "string", - "description": "Authentication type: public, password, email, or sso", - "enum": [ - "public", - "password", - "email", - "sso" - ], - "default": "public" + }, + }, + resultSchema: undefined, + }, + deploy_chat: { + parameters: { + type: 'object', + properties: { + action: { + type: 'string', + description: 'Whether to deploy or undeploy the chat interface', + enum: ['deploy', 'undeploy'], + default: 'deploy', }, - "description": { - "type": "string", - "description": "Optional description for the chat" + allowedEmails: { + type: 'array', + description: 'List of allowed emails/domains for email or SSO auth', + items: { + type: 'string', + }, }, - "identifier": { - "type": "string", - "description": "URL slug for the chat (lowercase letters, numbers, hyphens only)" + authType: { + type: 'string', + description: 'Authentication type: public, password, email, or sso', + enum: ['public', 'password', 'email', 'sso'], + default: 'public', }, - "outputConfigs": { - "type": "array", - "description": "Output configurations specifying which block outputs to display in chat", - "items": { - "type": "object", - "properties": { - "blockId": { - "type": "string", - "description": "The block UUID" + description: { + type: 'string', + description: 'Optional description for the chat', + }, + identifier: { + type: 'string', + description: 'URL slug for the chat (lowercase letters, numbers, hyphens only)', + }, + outputConfigs: { + type: 'array', + description: 'Output configurations specifying which block outputs to display in chat', + items: { + type: 'object', + properties: { + blockId: { + type: 'string', + description: 'The block UUID', }, - "path": { - "type": "string", - "description": "The output path (e.g. 'response', 'response.content')" - } - }, - "required": [ - "blockId", - "path" - ] - } - }, - "password": { - "type": "string", - "description": "Password for password-protected chats" - }, - "title": { - "type": "string", - "description": "Display title for the chat interface" - }, - "welcomeMessage": { - "type": "string", - "description": "Welcome message shown to users" - }, - "workflowId": { - "type": "string", - "description": "Workflow ID to deploy (required in workspace context)" - } - } - }, - resultSchema: undefined, - }, - ["deploy_mcp"]: { - parameters: { - "type": "object", - "properties": { - "parameterDescriptions": { - "type": "array", - "description": "Array of parameter descriptions for the tool", - "items": { - "type": "object", - "properties": { - "description": { - "type": "string", - "description": "Parameter description" + path: { + type: 'string', + description: "The output path (e.g. 'response', 'response.content')", }, - "name": { - "type": "string", - "description": "Parameter name" - } }, - "required": [ - "name", - "description" - ] - } + required: ['blockId', 'path'], + }, }, - "serverId": { - "type": "string", - "description": "Required: server ID from list_workspace_mcp_servers" + password: { + type: 'string', + description: 'Password for password-protected chats', }, - "toolDescription": { - "type": "string", - "description": "Description for the MCP tool" + title: { + type: 'string', + description: 'Display title for the chat interface', }, - "toolName": { - "type": "string", - "description": "Name for the MCP tool (defaults to workflow name)" + welcomeMessage: { + type: 'string', + description: 'Welcome message shown to users', + }, + workflowId: { + type: 'string', + description: 'Workflow ID to deploy (required in workspace context)', }, - "workflowId": { - "type": "string", - "description": "Workflow ID (defaults to active workflow)" - } }, - "required": [ - "serverId" - ] }, resultSchema: undefined, }, - ["download_to_workspace_file"]: { + deploy_mcp: { parameters: { - "type": "object", - "properties": { - "fileName": { - "type": "string", - "description": "Optional workspace file name to save as. If omitted, the name is inferred from the response or URL." - }, - "url": { - "type": "string", - "description": "Direct URL of the file to download, such as an image CDN URL ending in .png or .jpg" - } - }, - "required": [ - "url" - ] - }, - resultSchema: undefined, - }, - ["edit_workflow"]: { - parameters: { - "type": "object", - "properties": { - "operations": { - "type": "array", - "description": "Array of edit operations", - "items": { - "type": "object", - "properties": { - "block_id": { - "type": "string", - "description": "Block ID for the operation. For add operations, this will be the desired ID for the new block." + type: 'object', + properties: { + parameterDescriptions: { + type: 'array', + description: 'Array of parameter descriptions for the tool', + items: { + type: 'object', + properties: { + description: { + type: 'string', + description: 'Parameter description', }, - "operation_type": { - "type": "string", - "description": "Type of operation to perform", - "enum": [ - "add", - "edit", - "delete", - "insert_into_subflow", - "extract_from_subflow" - ] + name: { + type: 'string', + description: 'Parameter name', }, - "params": { - "type": "object", - "description": "Parameters for the operation. \nFor edit: {\"inputs\": {\"temperature\": 0.5}} NOT {\"subBlocks\": {\"temperature\": {\"value\": 0.5}}}\nFor add: {\"type\": \"agent\", \"name\": \"My Agent\", \"inputs\": {\"model\": \"gpt-4o\"}}\nFor delete: {} (empty object)" - } }, - "required": [ - "operation_type", - "block_id", - "params" - ] - } + required: ['name', 'description'], + }, + }, + serverId: { + type: 'string', + description: 'Required: server ID from list_workspace_mcp_servers', + }, + toolDescription: { + type: 'string', + description: 'Description for the MCP tool', + }, + toolName: { + type: 'string', + description: 'Name for the MCP tool (defaults to workflow name)', + }, + workflowId: { + type: 'string', + description: 'Workflow ID (defaults to active workflow)', }, - "workflowId": { - "type": "string", - "description": "Optional workflow ID to edit. If not provided, uses the current workflow in context." - } }, - "required": [ - "operations" - ] + required: ['serverId'], }, resultSchema: undefined, }, - ["file"]: { + download_to_workspace_file: { parameters: { - "type": "object" - }, - resultSchema: undefined, - }, - ["function_execute"]: { - parameters: { - "type": "object", - "properties": { - "code": { - "type": "string", - "description": "Code to execute. For JS: raw statements auto-wrapped in async context. For Python: full script. For shell: bash script with access to pre-installed CLI tools and workspace env vars as $VAR_NAME." + type: 'object', + properties: { + fileName: { + type: 'string', + description: + 'Optional workspace file name to save as. If omitted, the name is inferred from the response or URL.', }, - "inputFiles": { - "type": "array", - "description": "Canonical workspace file IDs to mount in the sandbox. Discover IDs via read(\"files/{name}/meta.json\") or glob(\"files/by-id/*/meta.json\"). Mounted path: /home/user/files/{fileId}/{originalName}. Example: [\"wf_123\"]", - "items": { - "type": "string" - } + url: { + type: 'string', + description: + 'Direct URL of the file to download, such as an image CDN URL ending in .png or .jpg', }, - "inputTables": { - "type": "array", - "description": "Table IDs to mount as CSV files in the sandbox. Each table appears at /home/user/tables/{tableId}.csv with a header row. Example: [\"tbl_abc123\"]", - "items": { - "type": "string" - } - }, - "language": { - "type": "string", - "description": "Execution language.", - "enum": [ - "javascript", - "python", - "shell" - ] - }, - "outputFormat": { - "type": "string", - "description": "Format for outputPath. Determines how the code result is serialized. If omitted, inferred from outputPath file extension.", - "enum": [ - "json", - "csv", - "txt", - "md", - "html" - ] - }, - "outputMimeType": { - "type": "string", - "description": "MIME type for outputSandboxPath export. Required for binary files: image/png, image/jpeg, application/pdf, etc. Omit for text files." - }, - "outputPath": { - "type": "string", - "description": "Pipe output directly to a NEW workspace file instead of returning in context. ALWAYS use this instead of a separate workspace_file write call. Use a flat path like \"files/result.json\" — nested paths are not supported." - }, - "outputSandboxPath": { - "type": "string", - "description": "Path to a file created inside the sandbox that should be exported to the workspace. Use together with outputPath." - }, - "outputTable": { - "type": "string", - "description": "Table ID to overwrite with the code's return value. Code MUST return an array of objects where keys match column names. All existing rows are replaced. Example: \"tbl_abc123\"" - } }, - "required": [ - "code" - ] + required: ['url'], }, resultSchema: undefined, }, - ["generate_api_key"]: { + edit_workflow: { parameters: { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "A descriptive name for the API key (e.g., 'production-key', 'dev-testing')." - }, - "workspaceId": { - "type": "string", - "description": "Optional workspace ID. Defaults to user's default workspace." - } - }, - "required": [ - "name" - ] - }, - resultSchema: undefined, - }, - ["generate_image"]: { - parameters: { - "type": "object", - "properties": { - "aspectRatio": { - "type": "string", - "description": "Aspect ratio for the generated image.", - "enum": [ - "1:1", - "16:9", - "9:16", - "4:3", - "3:4" - ] - }, - "fileName": { - "type": "string", - "description": "Output file name. Defaults to \"generated-image.png\". Workspace files are flat, so pass a plain file name, not a nested path." - }, - "overwriteFileId": { - "type": "string", - "description": "If provided, overwrites the existing workspace file with this ID instead of creating a new file. Use this when the user asks to update or redo a previously generated image. The file ID is returned by previous generate_image or generate_visualization calls (fileId field), or can be found via read(\"files/by-id/{fileId}/meta.json\")." - }, - "prompt": { - "type": "string", - "description": "Detailed text description of the image to generate, or editing instructions when used with editFileId." - }, - "referenceFileIds": { - "type": "array", - "description": "File IDs of workspace images to include as context for the generation. All images are sent alongside the prompt. Use for: editing a single image (1 file), compositing multiple images together (2+ files), style transfer, face swapping, etc. Order matters — list the primary/base image first.", - "items": { - "type": "string" - } - } - }, - "required": [ - "prompt" - ] - }, - resultSchema: undefined, - }, - ["generate_visualization"]: { - parameters: { - "type": "object", - "properties": { - "code": { - "type": "string", - "description": "Python code that generates a visualization using matplotlib. MUST call plt.savefig('/home/user/output.png', dpi=150, bbox_inches='tight') to produce output." - }, - "fileName": { - "type": "string", - "description": "Output file name. Defaults to \"chart.png\". Workspace files are flat, so pass a plain file name, not a nested path." - }, - "inputFiles": { - "type": "array", - "description": "Canonical workspace file IDs to mount in the sandbox. Discover IDs via read(\"files/{name}/meta.json\") or glob(\"files/by-id/*/meta.json\"). Mounted path: /home/user/files/{fileId}/{originalName}.", - "items": { - "type": "string" - } - }, - "inputTables": { - "type": "array", - "description": "Table IDs to mount as CSV files in the sandbox. Each table appears at /home/user/tables/{tableId}.csv with a header row. Read with pandas: pd.read_csv('/home/user/tables/tbl_xxx.csv')", - "items": { - "type": "string" - } - }, - "overwriteFileId": { - "type": "string", - "description": "If provided, overwrites the existing workspace file with this ID instead of creating a new file. Use this when the user asks to update or redo a previously generated chart. The file ID is returned by previous generate_visualization or generate_image calls (fileId field), or can be found via read(\"files/by-id/{fileId}/meta.json\")." - } - }, - "required": [ - "code" - ] - }, - resultSchema: undefined, - }, - ["get_block_outputs"]: { - parameters: { - "type": "object", - "properties": { - "blockIds": { - "type": "array", - "description": "Optional array of block UUIDs. If provided, returns outputs only for those blocks. If not provided, returns outputs for all blocks in the workflow.", - "items": { - "type": "string" - } - }, - "workflowId": { - "type": "string", - "description": "Optional workflow ID. If not provided, uses the current workflow in context." - } - } - }, - resultSchema: undefined, - }, - ["get_block_upstream_references"]: { - parameters: { - "type": "object", - "properties": { - "blockIds": { - "type": "array", - "description": "Required array of block UUIDs (minimum 1). Returns what each block can reference based on its position in the workflow graph.", - "items": { - "type": "string" - } - }, - "workflowId": { - "type": "string", - "description": "Optional workflow ID. If not provided, uses the current workflow in context." - } - }, - "required": [ - "blockIds" - ] - }, - resultSchema: undefined, - }, - ["get_deployed_workflow_state"]: { - parameters: { - "type": "object", - "properties": { - "workflowId": { - "type": "string", - "description": "Optional workflow ID. If not provided, uses the current workflow in context." - } - } - }, - resultSchema: undefined, - }, - ["get_deployment_version"]: { - parameters: { - "type": "object", - "properties": { - "version": { - "type": "number", - "description": "The deployment version number" - }, - "workflowId": { - "type": "string", - "description": "The workflow ID" - } - }, - "required": [ - "workflowId", - "version" - ] - }, - resultSchema: undefined, - }, - ["get_execution_summary"]: { - parameters: { - "type": "object", - "properties": { - "limit": { - "type": "number", - "description": "Max number of executions to return (default: 10, max: 20)." - }, - "status": { - "type": "string", - "description": "Filter by status: 'success', 'error', or 'all' (default: 'all').", - "enum": [ - "success", - "error", - "all" - ] - }, - "workflowId": { - "type": "string", - "description": "Optional workflow ID. If omitted, returns executions across all workflows in the workspace." - }, - "workspaceId": { - "type": "string", - "description": "Workspace ID to scope executions to." - } - }, - "required": [ - "workspaceId" - ] - }, - resultSchema: undefined, - }, - ["get_job_logs"]: { - parameters: { - "type": "object", - "properties": { - "executionId": { - "type": "string", - "description": "Optional execution ID for a specific run." - }, - "includeDetails": { - "type": "boolean", - "description": "Include tool calls, outputs, and cost details." - }, - "jobId": { - "type": "string", - "description": "The job (schedule) ID to get logs for." - }, - "limit": { - "type": "number", - "description": "Max number of entries (default: 3, max: 5)" - } - }, - "required": [ - "jobId" - ] - }, - resultSchema: undefined, - }, - ["get_page_contents"]: { - parameters: { - "type": "object", - "properties": { - "include_highlights": { - "type": "boolean", - "description": "Include key highlights (default false)" - }, - "include_summary": { - "type": "boolean", - "description": "Include AI-generated summary (default false)" - }, - "include_text": { - "type": "boolean", - "description": "Include full page text (default true)" - }, - "urls": { - "type": "array", - "description": "URLs to get content from (max 10)", - "items": { - "type": "string" - } - } - }, - "required": [ - "urls" - ] - }, - resultSchema: undefined, - }, - ["get_platform_actions"]: { - parameters: { - "type": "object", - "properties": {} - }, - resultSchema: undefined, - }, - ["get_workflow_data"]: { - parameters: { - "type": "object", - "properties": { - "data_type": { - "type": "string", - "description": "The type of workflow data to retrieve", - "enum": [ - "global_variables", - "custom_tools", - "mcp_tools", - "files" - ] - }, - "workflowId": { - "type": "string", - "description": "Optional workflow ID. If not provided, uses the current workflow in context." - } - }, - "required": [ - "data_type" - ] - }, - resultSchema: undefined, - }, - ["get_workflow_logs"]: { - parameters: { - "type": "object", - "properties": { - "executionId": { - "type": "string", - "description": "Optional execution ID to get logs for a specific execution. Use with get_execution_summary to find execution IDs first." - }, - "includeDetails": { - "type": "boolean", - "description": "Include detailed info" - }, - "limit": { - "type": "number", - "description": "Max number of entries (hard limit: 3)" - }, - "workflowId": { - "type": "string", - "description": "Optional workflow ID. If not provided, uses the current workflow in context." - } - } - }, - resultSchema: undefined, - }, - ["glob"]: { - parameters: { - "type": "object", - "properties": { - "pattern": { - "type": "string", - "description": "Glob pattern to match file paths. Supports * (any segment) and ** (any depth)." - } - }, - "required": [ - "pattern" - ] - }, - resultSchema: undefined, - }, - ["grep"]: { - parameters: { - "type": "object", - "properties": { - "context": { - "type": "number", - "description": "Number of lines to show before and after each match. Only applies to output_mode 'content'." - }, - "ignoreCase": { - "type": "boolean", - "description": "Case insensitive search (default false)." - }, - "lineNumbers": { - "type": "boolean", - "description": "Include line numbers in output (default true). Only applies to output_mode 'content'." - }, - "maxResults": { - "type": "number", - "description": "Maximum number of matches to return (default 50)." - }, - "output_mode": { - "type": "string", - "description": "Output mode: 'content' shows matching lines (default), 'files_with_matches' shows only file paths, 'count' shows match counts per file.", - "enum": [ - "content", - "files_with_matches", - "count" - ] - }, - "path": { - "type": "string", - "description": "Optional path prefix to scope the search (e.g. 'workflows/', 'environment/', 'internal/', 'components/blocks/')." - }, - "pattern": { - "type": "string", - "description": "Regex pattern to search for in file contents." - } - }, - "required": [ - "pattern" - ] - }, - resultSchema: undefined, - }, - ["job"]: { - parameters: { - "properties": { - "request": { - "description": "What job action is needed.", - "type": "string" - } - }, - "required": [ - "request" - ], - "type": "object" - }, - resultSchema: undefined, - }, - ["knowledge"]: { - parameters: { - "properties": { - "request": { - "description": "What knowledge base action is needed.", - "type": "string" - } - }, - "required": [ - "request" - ], - "type": "object" - }, - resultSchema: undefined, - }, - ["knowledge_base"]: { - parameters: { - "type": "object", - "properties": { - "args": { - "type": "object", - "description": "Arguments for the operation", - "properties": { - "apiKey": { - "type": "string", - "description": "API key for API-key-based connectors (required when connector auth mode is apiKey)" + type: 'object', + properties: { + operations: { + type: 'array', + description: 'Array of edit operations', + items: { + type: 'object', + properties: { + block_id: { + type: 'string', + description: + 'Block ID for the operation. For add operations, this will be the desired ID for the new block.', + }, + operation_type: { + type: 'string', + description: 'Type of operation to perform', + enum: ['add', 'edit', 'delete', 'insert_into_subflow', 'extract_from_subflow'], + }, + params: { + type: 'object', + description: + 'Parameters for the operation. \nFor edit: {"inputs": {"temperature": 0.5}} NOT {"subBlocks": {"temperature": {"value": 0.5}}}\nFor add: {"type": "agent", "name": "My Agent", "inputs": {"model": "gpt-4o"}}\nFor delete: {} (empty object)', + }, }, - "chunkingConfig": { - "type": "object", - "description": "Chunking configuration (optional for 'create')", - "properties": { - "maxSize": { - "type": "number", - "description": "Maximum chunk size (100-4000, default: 1024)", - "default": 1024 + required: ['operation_type', 'block_id', 'params'], + }, + }, + workflowId: { + type: 'string', + description: + 'Optional workflow ID to edit. If not provided, uses the current workflow in context.', + }, + }, + required: ['operations'], + }, + resultSchema: undefined, + }, + file: { + parameters: { + type: 'object', + }, + resultSchema: undefined, + }, + function_execute: { + parameters: { + type: 'object', + properties: { + code: { + type: 'string', + description: + 'Code to execute. For JS: raw statements auto-wrapped in async context. For Python: full script. For shell: bash script with access to pre-installed CLI tools and workspace env vars as $VAR_NAME.', + }, + inputFiles: { + type: 'array', + description: + 'Canonical workspace file IDs to mount in the sandbox. Discover IDs via read("files/{name}/meta.json") or glob("files/by-id/*/meta.json"). Mounted path: /home/user/files/{fileId}/{originalName}. Example: ["wf_123"]', + items: { + type: 'string', + }, + }, + inputTables: { + type: 'array', + description: + 'Table IDs to mount as CSV files in the sandbox. Each table appears at /home/user/tables/{tableId}.csv with a header row. Example: ["tbl_abc123"]', + items: { + type: 'string', + }, + }, + language: { + type: 'string', + description: 'Execution language.', + enum: ['javascript', 'python', 'shell'], + }, + outputFormat: { + type: 'string', + description: + 'Format for outputPath. Determines how the code result is serialized. If omitted, inferred from outputPath file extension.', + enum: ['json', 'csv', 'txt', 'md', 'html'], + }, + outputMimeType: { + type: 'string', + description: + 'MIME type for outputSandboxPath export. Required for binary files: image/png, image/jpeg, application/pdf, etc. Omit for text files.', + }, + outputPath: { + type: 'string', + description: + 'Pipe output directly to a NEW workspace file instead of returning in context. ALWAYS use this instead of a separate workspace_file write call. Use a flat path like "files/result.json" — nested paths are not supported.', + }, + outputSandboxPath: { + type: 'string', + description: + 'Path to a file created inside the sandbox that should be exported to the workspace. Use together with outputPath.', + }, + outputTable: { + type: 'string', + description: + 'Table ID to overwrite with the code\'s return value. Code MUST return an array of objects where keys match column names. All existing rows are replaced. Example: "tbl_abc123"', + }, + }, + required: ['code'], + }, + resultSchema: undefined, + }, + generate_api_key: { + parameters: { + type: 'object', + properties: { + name: { + type: 'string', + description: + "A descriptive name for the API key (e.g., 'production-key', 'dev-testing').", + }, + workspaceId: { + type: 'string', + description: "Optional workspace ID. Defaults to user's default workspace.", + }, + }, + required: ['name'], + }, + resultSchema: undefined, + }, + generate_image: { + parameters: { + type: 'object', + properties: { + aspectRatio: { + type: 'string', + description: 'Aspect ratio for the generated image.', + enum: ['1:1', '16:9', '9:16', '4:3', '3:4'], + }, + fileName: { + type: 'string', + description: + 'Output file name. Defaults to "generated-image.png". Workspace files are flat, so pass a plain file name, not a nested path.', + }, + overwriteFileId: { + type: 'string', + description: + 'If provided, overwrites the existing workspace file with this ID instead of creating a new file. Use this when the user asks to update or redo a previously generated image. The file ID is returned by previous generate_image or generate_visualization calls (fileId field), or can be found via read("files/by-id/{fileId}/meta.json").', + }, + prompt: { + type: 'string', + description: + 'Detailed text description of the image to generate, or editing instructions when used with editFileId.', + }, + referenceFileIds: { + type: 'array', + description: + 'File IDs of workspace images to include as context for the generation. All images are sent alongside the prompt. Use for: editing a single image (1 file), compositing multiple images together (2+ files), style transfer, face swapping, etc. Order matters — list the primary/base image first.', + items: { + type: 'string', + }, + }, + }, + required: ['prompt'], + }, + resultSchema: undefined, + }, + generate_visualization: { + parameters: { + type: 'object', + properties: { + code: { + type: 'string', + description: + "Python code that generates a visualization using matplotlib. MUST call plt.savefig('/home/user/output.png', dpi=150, bbox_inches='tight') to produce output.", + }, + fileName: { + type: 'string', + description: + 'Output file name. Defaults to "chart.png". Workspace files are flat, so pass a plain file name, not a nested path.', + }, + inputFiles: { + type: 'array', + description: + 'Canonical workspace file IDs to mount in the sandbox. Discover IDs via read("files/{name}/meta.json") or glob("files/by-id/*/meta.json"). Mounted path: /home/user/files/{fileId}/{originalName}.', + items: { + type: 'string', + }, + }, + inputTables: { + type: 'array', + description: + "Table IDs to mount as CSV files in the sandbox. Each table appears at /home/user/tables/{tableId}.csv with a header row. Read with pandas: pd.read_csv('/home/user/tables/tbl_xxx.csv')", + items: { + type: 'string', + }, + }, + overwriteFileId: { + type: 'string', + description: + 'If provided, overwrites the existing workspace file with this ID instead of creating a new file. Use this when the user asks to update or redo a previously generated chart. The file ID is returned by previous generate_visualization or generate_image calls (fileId field), or can be found via read("files/by-id/{fileId}/meta.json").', + }, + }, + required: ['code'], + }, + resultSchema: undefined, + }, + get_block_outputs: { + parameters: { + type: 'object', + properties: { + blockIds: { + type: 'array', + description: + 'Optional array of block UUIDs. If provided, returns outputs only for those blocks. If not provided, returns outputs for all blocks in the workflow.', + items: { + type: 'string', + }, + }, + workflowId: { + type: 'string', + description: + 'Optional workflow ID. If not provided, uses the current workflow in context.', + }, + }, + }, + resultSchema: undefined, + }, + get_block_upstream_references: { + parameters: { + type: 'object', + properties: { + blockIds: { + type: 'array', + description: + 'Required array of block UUIDs (minimum 1). Returns what each block can reference based on its position in the workflow graph.', + items: { + type: 'string', + }, + }, + workflowId: { + type: 'string', + description: + 'Optional workflow ID. If not provided, uses the current workflow in context.', + }, + }, + required: ['blockIds'], + }, + resultSchema: undefined, + }, + get_deployed_workflow_state: { + parameters: { + type: 'object', + properties: { + workflowId: { + type: 'string', + description: + 'Optional workflow ID. If not provided, uses the current workflow in context.', + }, + }, + }, + resultSchema: undefined, + }, + get_deployment_version: { + parameters: { + type: 'object', + properties: { + version: { + type: 'number', + description: 'The deployment version number', + }, + workflowId: { + type: 'string', + description: 'The workflow ID', + }, + }, + required: ['workflowId', 'version'], + }, + resultSchema: undefined, + }, + get_execution_summary: { + parameters: { + type: 'object', + properties: { + limit: { + type: 'number', + description: 'Max number of executions to return (default: 10, max: 20).', + }, + status: { + type: 'string', + description: "Filter by status: 'success', 'error', or 'all' (default: 'all').", + enum: ['success', 'error', 'all'], + }, + workflowId: { + type: 'string', + description: + 'Optional workflow ID. If omitted, returns executions across all workflows in the workspace.', + }, + workspaceId: { + type: 'string', + description: 'Workspace ID to scope executions to.', + }, + }, + required: ['workspaceId'], + }, + resultSchema: undefined, + }, + get_job_logs: { + parameters: { + type: 'object', + properties: { + executionId: { + type: 'string', + description: 'Optional execution ID for a specific run.', + }, + includeDetails: { + type: 'boolean', + description: 'Include tool calls, outputs, and cost details.', + }, + jobId: { + type: 'string', + description: 'The job (schedule) ID to get logs for.', + }, + limit: { + type: 'number', + description: 'Max number of entries (default: 3, max: 5)', + }, + }, + required: ['jobId'], + }, + resultSchema: undefined, + }, + get_page_contents: { + parameters: { + type: 'object', + properties: { + include_highlights: { + type: 'boolean', + description: 'Include key highlights (default false)', + }, + include_summary: { + type: 'boolean', + description: 'Include AI-generated summary (default false)', + }, + include_text: { + type: 'boolean', + description: 'Include full page text (default true)', + }, + urls: { + type: 'array', + description: 'URLs to get content from (max 10)', + items: { + type: 'string', + }, + }, + }, + required: ['urls'], + }, + resultSchema: undefined, + }, + get_platform_actions: { + parameters: { + type: 'object', + properties: {}, + }, + resultSchema: undefined, + }, + get_workflow_data: { + parameters: { + type: 'object', + properties: { + data_type: { + type: 'string', + description: 'The type of workflow data to retrieve', + enum: ['global_variables', 'custom_tools', 'mcp_tools', 'files'], + }, + workflowId: { + type: 'string', + description: + 'Optional workflow ID. If not provided, uses the current workflow in context.', + }, + }, + required: ['data_type'], + }, + resultSchema: undefined, + }, + get_workflow_logs: { + parameters: { + type: 'object', + properties: { + executionId: { + type: 'string', + description: + 'Optional execution ID to get logs for a specific execution. Use with get_execution_summary to find execution IDs first.', + }, + includeDetails: { + type: 'boolean', + description: 'Include detailed info', + }, + limit: { + type: 'number', + description: 'Max number of entries (hard limit: 3)', + }, + workflowId: { + type: 'string', + description: + 'Optional workflow ID. If not provided, uses the current workflow in context.', + }, + }, + }, + resultSchema: undefined, + }, + glob: { + parameters: { + type: 'object', + properties: { + pattern: { + type: 'string', + description: + 'Glob pattern to match file paths. Supports * (any segment) and ** (any depth).', + }, + }, + required: ['pattern'], + }, + resultSchema: undefined, + }, + grep: { + parameters: { + type: 'object', + properties: { + context: { + type: 'number', + description: + "Number of lines to show before and after each match. Only applies to output_mode 'content'.", + }, + ignoreCase: { + type: 'boolean', + description: 'Case insensitive search (default false).', + }, + lineNumbers: { + type: 'boolean', + description: + "Include line numbers in output (default true). Only applies to output_mode 'content'.", + }, + maxResults: { + type: 'number', + description: 'Maximum number of matches to return (default 50).', + }, + output_mode: { + type: 'string', + description: + "Output mode: 'content' shows matching lines (default), 'files_with_matches' shows only file paths, 'count' shows match counts per file.", + enum: ['content', 'files_with_matches', 'count'], + }, + path: { + type: 'string', + description: + "Optional path prefix to scope the search (e.g. 'workflows/', 'environment/', 'internal/', 'components/blocks/').", + }, + pattern: { + type: 'string', + description: 'Regex pattern to search for in file contents.', + }, + }, + required: ['pattern'], + }, + resultSchema: undefined, + }, + job: { + parameters: { + properties: { + request: { + description: 'What job action is needed.', + type: 'string', + }, + }, + required: ['request'], + type: 'object', + }, + resultSchema: undefined, + }, + knowledge: { + parameters: { + properties: { + request: { + description: 'What knowledge base action is needed.', + type: 'string', + }, + }, + required: ['request'], + type: 'object', + }, + resultSchema: undefined, + }, + knowledge_base: { + parameters: { + type: 'object', + properties: { + args: { + type: 'object', + description: 'Arguments for the operation', + properties: { + apiKey: { + type: 'string', + description: + 'API key for API-key-based connectors (required when connector auth mode is apiKey)', + }, + chunkingConfig: { + type: 'object', + description: "Chunking configuration (optional for 'create')", + properties: { + maxSize: { + type: 'number', + description: 'Maximum chunk size (100-4000, default: 1024)', + default: 1024, }, - "minSize": { - "type": "number", - "description": "Minimum chunk size (1-2000, default: 1)", - "default": 1 + minSize: { + type: 'number', + description: 'Minimum chunk size (1-2000, default: 1)', + default: 1, }, - "overlap": { - "type": "number", - "description": "Overlap between chunks (0-500, default: 200)", - "default": 200 - } - } + overlap: { + type: 'number', + description: 'Overlap between chunks (0-500, default: 200)', + default: 200, + }, + }, }, - "connectorId": { - "type": "string", - "description": "Connector ID (required for update_connector, delete_connector, sync_connector)" + connectorId: { + type: 'string', + description: + 'Connector ID (required for update_connector, delete_connector, sync_connector)', }, - "connectorStatus": { - "type": "string", - "description": "Connector status (optional for update_connector)", - "enum": [ - "active", - "paused" - ] + connectorStatus: { + type: 'string', + description: 'Connector status (optional for update_connector)', + enum: ['active', 'paused'], }, - "connectorType": { - "type": "string", - "description": "Connector type from registry, e.g. 'confluence', 'google_drive', 'notion' (required for add_connector). Read knowledgebases/connectors/{type}.json for the config schema." + connectorType: { + type: 'string', + description: + "Connector type from registry, e.g. 'confluence', 'google_drive', 'notion' (required for add_connector). Read knowledgebases/connectors/{type}.json for the config schema.", }, - "credentialId": { - "type": "string", - "description": "OAuth credential ID from environment/credentials.json (required for OAuth connectors)" + credentialId: { + type: 'string', + description: + 'OAuth credential ID from environment/credentials.json (required for OAuth connectors)', }, - "description": { - "type": "string", - "description": "Description of the knowledge base (optional for 'create')" + description: { + type: 'string', + description: "Description of the knowledge base (optional for 'create')", }, - "disabledTagIds": { - "type": "array", - "description": "Tag definition IDs to opt out of (optional for add_connector). See tagDefinitions in the connector schema." + disabledTagIds: { + type: 'array', + description: + 'Tag definition IDs to opt out of (optional for add_connector). See tagDefinitions in the connector schema.', }, - "documentId": { - "type": "string", - "description": "Document ID (required for delete_document, update_document)" + documentId: { + type: 'string', + description: 'Document ID (required for delete_document, update_document)', }, - "enabled": { - "type": "boolean", - "description": "Enable/disable a document (optional for update_document)" + enabled: { + type: 'boolean', + description: 'Enable/disable a document (optional for update_document)', }, - "fileId": { - "type": "string", - "description": "Canonical workspace file ID to add as a document (preferred for add_file). Discover via read(\"files/{name}/meta.json\") or glob(\"files/by-id/*/meta.json\")." + fileId: { + type: 'string', + description: + 'Canonical workspace file ID to add as a document (preferred for add_file). Discover via read("files/{name}/meta.json") or glob("files/by-id/*/meta.json").', }, - "filePath": { - "type": "string", - "description": "Legacy workspace file reference for add_file. Prefer fileId." + filePath: { + type: 'string', + description: 'Legacy workspace file reference for add_file. Prefer fileId.', }, - "filename": { - "type": "string", - "description": "New filename for a document (optional for update_document)" + filename: { + type: 'string', + description: 'New filename for a document (optional for update_document)', }, - "knowledgeBaseId": { - "type": "string", - "description": "Knowledge base ID (required for get, query, add_file, list_tags, create_tag, get_tag_usage)" + knowledgeBaseId: { + type: 'string', + description: + 'Knowledge base ID (required for get, query, add_file, list_tags, create_tag, get_tag_usage)', }, - "name": { - "type": "string", - "description": "Name of the knowledge base (required for 'create')" + name: { + type: 'string', + description: "Name of the knowledge base (required for 'create')", }, - "query": { - "type": "string", - "description": "Search query text (required for 'query')" + query: { + type: 'string', + description: "Search query text (required for 'query')", }, - "sourceConfig": { - "type": "object", - "description": "Connector-specific configuration matching the configFields in knowledgebases/connectors/{type}.json" + sourceConfig: { + type: 'object', + description: + 'Connector-specific configuration matching the configFields in knowledgebases/connectors/{type}.json', }, - "syncIntervalMinutes": { - "type": "number", - "description": "Sync interval in minutes: 60 (hourly), 360 (6h), 1440 (daily), 10080 (weekly), 0 (manual only). Default: 1440", - "default": 1440 + syncIntervalMinutes: { + type: 'number', + description: + 'Sync interval in minutes: 60 (hourly), 360 (6h), 1440 (daily), 10080 (weekly), 0 (manual only). Default: 1440', + default: 1440, }, - "tagDefinitionId": { - "type": "string", - "description": "Tag definition ID (required for update_tag, delete_tag)" + tagDefinitionId: { + type: 'string', + description: 'Tag definition ID (required for update_tag, delete_tag)', }, - "tagDisplayName": { - "type": "string", - "description": "Display name for the tag (required for create_tag, optional for update_tag)" + tagDisplayName: { + type: 'string', + description: + 'Display name for the tag (required for create_tag, optional for update_tag)', }, - "tagFieldType": { - "type": "string", - "description": "Field type: text, number, date, boolean (optional for create_tag, defaults to text)", - "enum": [ - "text", - "number", - "date", - "boolean" - ] + tagFieldType: { + type: 'string', + description: + 'Field type: text, number, date, boolean (optional for create_tag, defaults to text)', + enum: ['text', 'number', 'date', 'boolean'], }, - "topK": { - "type": "number", - "description": "Number of results to return (1-50, default: 5)", - "default": 5 + topK: { + type: 'number', + description: 'Number of results to return (1-50, default: 5)', + default: 5, }, - "workspaceId": { - "type": "string", - "description": "Workspace ID (required for 'create', optional filter for 'list')" - } - } + workspaceId: { + type: 'string', + description: "Workspace ID (required for 'create', optional filter for 'list')", + }, + }, + }, + operation: { + type: 'string', + description: 'The operation to perform', + enum: [ + 'create', + 'get', + 'query', + 'add_file', + 'update', + 'delete', + 'delete_document', + 'update_document', + 'list_tags', + 'create_tag', + 'update_tag', + 'delete_tag', + 'get_tag_usage', + 'add_connector', + 'update_connector', + 'delete_connector', + 'sync_connector', + ], }, - "operation": { - "type": "string", - "description": "The operation to perform", - "enum": [ - "create", - "get", - "query", - "add_file", - "update", - "delete", - "delete_document", - "update_document", - "list_tags", - "create_tag", - "update_tag", - "delete_tag", - "get_tag_usage", - "add_connector", - "update_connector", - "delete_connector", - "sync_connector" - ] - } }, - "required": [ - "operation", - "args" - ] + required: ['operation', 'args'], }, resultSchema: { - "type": "object", - "properties": { - "data": { - "type": "object", - "description": "Operation-specific result payload." + type: 'object', + properties: { + data: { + type: 'object', + description: 'Operation-specific result payload.', }, - "message": { - "type": "string", - "description": "Human-readable outcome summary." + message: { + type: 'string', + description: 'Human-readable outcome summary.', + }, + success: { + type: 'boolean', + description: 'Whether the operation succeeded.', }, - "success": { - "type": "boolean", - "description": "Whether the operation succeeded." - } }, - "required": [ - "success", - "message" - ] + required: ['success', 'message'], }, }, - ["list_folders"]: { + list_folders: { parameters: { - "type": "object", - "properties": { - "workspaceId": { - "type": "string", - "description": "Optional workspace ID to list folders for." - } - } - }, - resultSchema: undefined, - }, - ["list_user_workspaces"]: { - parameters: { - "type": "object", - "properties": {} - }, - resultSchema: undefined, - }, - ["list_workspace_mcp_servers"]: { - parameters: { - "type": "object", - "properties": { - "workspaceId": { - "type": "string", - "description": "Workspace ID (defaults to current workspace)" - } - } - }, - resultSchema: undefined, - }, - ["manage_credential"]: { - parameters: { - "type": "object", - "properties": { - "credentialId": { - "type": "string", - "description": "The credential ID (from environment/credentials.json)" + type: 'object', + properties: { + workspaceId: { + type: 'string', + description: 'Optional workspace ID to list folders for.', }, - "displayName": { - "type": "string", - "description": "New display name (required for rename)" - }, - "operation": { - "type": "string", - "description": "The operation to perform", - "enum": [ - "rename", - "delete" - ] - } }, - "required": [ - "operation", - "credentialId" - ] }, resultSchema: undefined, }, - ["manage_custom_tool"]: { + list_user_workspaces: { parameters: { - "type": "object", - "properties": { - "code": { - "type": "string", - "description": "The JavaScript code that executes when the tool is called (required for add). Parameters from schema are available as variables. Function body only - no signature or wrapping braces." + type: 'object', + properties: {}, + }, + resultSchema: undefined, + }, + list_workspace_mcp_servers: { + parameters: { + type: 'object', + properties: { + workspaceId: { + type: 'string', + description: 'Workspace ID (defaults to current workspace)', }, - "operation": { - "type": "string", - "description": "The operation to perform: 'add', 'edit', 'list', or 'delete'", - "enum": [ - "add", - "edit", - "delete", - "list" - ] + }, + }, + resultSchema: undefined, + }, + manage_credential: { + parameters: { + type: 'object', + properties: { + credentialId: { + type: 'string', + description: 'The credential ID (from environment/credentials.json)', }, - "schema": { - "type": "object", - "description": "The tool schema in OpenAI function calling format (required for add).", - "properties": { - "function": { - "type": "object", - "description": "The function definition", - "properties": { - "description": { - "type": "string", - "description": "What the function does" + displayName: { + type: 'string', + description: 'New display name (required for rename)', + }, + operation: { + type: 'string', + description: 'The operation to perform', + enum: ['rename', 'delete'], + }, + }, + required: ['operation', 'credentialId'], + }, + resultSchema: undefined, + }, + manage_custom_tool: { + parameters: { + type: 'object', + properties: { + code: { + type: 'string', + description: + 'The JavaScript code that executes when the tool is called (required for add). Parameters from schema are available as variables. Function body only - no signature or wrapping braces.', + }, + operation: { + type: 'string', + description: "The operation to perform: 'add', 'edit', 'list', or 'delete'", + enum: ['add', 'edit', 'delete', 'list'], + }, + schema: { + type: 'object', + description: 'The tool schema in OpenAI function calling format (required for add).', + properties: { + function: { + type: 'object', + description: 'The function definition', + properties: { + description: { + type: 'string', + description: 'What the function does', }, - "name": { - "type": "string", - "description": "The function name (camelCase)" + name: { + type: 'string', + description: 'The function name (camelCase)', }, - "parameters": { - "type": "object", - "description": "The function parameters schema", - "properties": { - "properties": { - "type": "object", - "description": "Parameter definitions as key-value pairs" + parameters: { + type: 'object', + description: 'The function parameters schema', + properties: { + properties: { + type: 'object', + description: 'Parameter definitions as key-value pairs', }, - "required": { - "type": "array", - "description": "Array of required parameter names", - "items": { - "type": "string" - } + required: { + type: 'array', + description: 'Array of required parameter names', + items: { + type: 'string', + }, + }, + type: { + type: 'string', + description: "Must be 'object'", }, - "type": { - "type": "string", - "description": "Must be 'object'" - } }, - "required": [ - "type", - "properties" - ] - } + required: ['type', 'properties'], + }, }, - "required": [ - "name", - "parameters" - ] + required: ['name', 'parameters'], + }, + type: { + type: 'string', + description: "Must be 'function'", }, - "type": { - "type": "string", - "description": "Must be 'function'" - } }, - "required": [ - "type", - "function" - ] + required: ['type', 'function'], + }, + toolId: { + type: 'string', + description: + "The ID of the custom tool (required for edit/delete). Must be the exact toolId from the get_workflow_data custom tool response - do not guess or construct it. DO NOT PROVIDE THE TOOL ID IF THE OPERATION IS 'ADD'.", }, - "toolId": { - "type": "string", - "description": "The ID of the custom tool (required for edit/delete). Must be the exact toolId from the get_workflow_data custom tool response - do not guess or construct it. DO NOT PROVIDE THE TOOL ID IF THE OPERATION IS 'ADD'." - } }, - "required": [ - "operation" - ] + required: ['operation'], }, resultSchema: undefined, }, - ["manage_job"]: { + manage_job: { parameters: { - "type": "object", - "properties": { - "args": { - "type": "object", - "description": "Operation-specific arguments. For create: {title, prompt, cron?, time?, timezone?, lifecycle?, successCondition?, maxRuns?}. For get/delete: {jobId}. For update: {jobId, title?, prompt?, cron?, timezone?, status?, lifecycle?, successCondition?, maxRuns?}. For list: no args needed.", - "properties": { - "cron": { - "type": "string", - "description": "Cron expression for recurring jobs" + type: 'object', + properties: { + args: { + type: 'object', + description: + 'Operation-specific arguments. For create: {title, prompt, cron?, time?, timezone?, lifecycle?, successCondition?, maxRuns?}. For get/delete: {jobId}. For update: {jobId, title?, prompt?, cron?, timezone?, status?, lifecycle?, successCondition?, maxRuns?}. For list: no args needed.', + properties: { + cron: { + type: 'string', + description: 'Cron expression for recurring jobs', }, - "jobId": { - "type": "string", - "description": "Job ID (required for get, update, delete)" + jobId: { + type: 'string', + description: 'Job ID (required for get, update, delete)', }, - "lifecycle": { - "type": "string", - "description": "'persistent' (default) or 'until_complete'. Until_complete jobs stop when complete_job is called." + lifecycle: { + type: 'string', + description: + "'persistent' (default) or 'until_complete'. Until_complete jobs stop when complete_job is called.", }, - "maxRuns": { - "type": "integer", - "description": "Max executions before auto-completing. Safety limit." + maxRuns: { + type: 'integer', + description: 'Max executions before auto-completing. Safety limit.', }, - "prompt": { - "type": "string", - "description": "The prompt to execute when the job fires" + prompt: { + type: 'string', + description: 'The prompt to execute when the job fires', }, - "status": { - "type": "string", - "description": "Job status: active, paused" + status: { + type: 'string', + description: 'Job status: active, paused', }, - "successCondition": { - "type": "string", - "description": "What must happen for the job to be considered complete (until_complete lifecycle)." + successCondition: { + type: 'string', + description: + 'What must happen for the job to be considered complete (until_complete lifecycle).', }, - "time": { - "type": "string", - "description": "ISO 8601 datetime for one-time jobs or cron start time" + time: { + type: 'string', + description: 'ISO 8601 datetime for one-time jobs or cron start time', }, - "timezone": { - "type": "string", - "description": "IANA timezone (e.g. America/New_York). Defaults to UTC." + timezone: { + type: 'string', + description: 'IANA timezone (e.g. America/New_York). Defaults to UTC.', }, - "title": { - "type": "string", - "description": "Short descriptive title for the job (e.g. 'Email Poller')" - } - } + title: { + type: 'string', + description: "Short descriptive title for the job (e.g. 'Email Poller')", + }, + }, + }, + operation: { + type: 'string', + description: 'The operation to perform: create, list, get, update, delete', + enum: ['create', 'list', 'get', 'update', 'delete'], }, - "operation": { - "type": "string", - "description": "The operation to perform: create, list, get, update, delete", - "enum": [ - "create", - "list", - "get", - "update", - "delete" - ] - } }, - "required": [ - "operation" - ] + required: ['operation'], }, resultSchema: undefined, }, - ["manage_mcp_tool"]: { + manage_mcp_tool: { parameters: { - "type": "object", - "properties": { - "config": { - "type": "object", - "description": "Required for add and edit. The MCP server configuration.", - "properties": { - "enabled": { - "type": "boolean", - "description": "Whether the server is enabled (default: true)" + type: 'object', + properties: { + config: { + type: 'object', + description: 'Required for add and edit. The MCP server configuration.', + properties: { + enabled: { + type: 'boolean', + description: 'Whether the server is enabled (default: true)', }, - "headers": { - "type": "object", - "description": "Optional HTTP headers to send with requests (key-value pairs)" + headers: { + type: 'object', + description: 'Optional HTTP headers to send with requests (key-value pairs)', }, - "name": { - "type": "string", - "description": "Display name for the MCP server" + name: { + type: 'string', + description: 'Display name for the MCP server', }, - "timeout": { - "type": "number", - "description": "Request timeout in milliseconds (default: 30000)" + timeout: { + type: 'number', + description: 'Request timeout in milliseconds (default: 30000)', }, - "transport": { - "type": "string", - "description": "Transport protocol: 'streamable-http' or 'sse'", - "enum": [ - "streamable-http", - "sse" - ], - "default": "streamable-http" + transport: { + type: 'string', + description: "Transport protocol: 'streamable-http' or 'sse'", + enum: ['streamable-http', 'sse'], + default: 'streamable-http', }, - "url": { - "type": "string", - "description": "The MCP server endpoint URL (required for add)" - } - } + url: { + type: 'string', + description: 'The MCP server endpoint URL (required for add)', + }, + }, }, - "operation": { - "type": "string", - "description": "The operation to perform: 'add', 'edit', 'list', or 'delete'", - "enum": [ - "add", - "edit", - "delete", - "list" - ] + operation: { + type: 'string', + description: "The operation to perform: 'add', 'edit', 'list', or 'delete'", + enum: ['add', 'edit', 'delete', 'list'], + }, + serverId: { + type: 'string', + description: + "Required for edit and delete. The database ID of the MCP server. DO NOT PROVIDE if operation is 'add' or 'list'.", }, - "serverId": { - "type": "string", - "description": "Required for edit and delete. The database ID of the MCP server. DO NOT PROVIDE if operation is 'add' or 'list'." - } }, - "required": [ - "operation" - ] + required: ['operation'], }, resultSchema: undefined, }, - ["manage_skill"]: { + manage_skill: { parameters: { - "type": "object", - "properties": { - "content": { - "type": "string", - "description": "Markdown instructions for the skill. Required for add, optional for edit." + type: 'object', + properties: { + content: { + type: 'string', + description: 'Markdown instructions for the skill. Required for add, optional for edit.', }, - "description": { - "type": "string", - "description": "Short description of the skill. Required for add, optional for edit." + description: { + type: 'string', + description: 'Short description of the skill. Required for add, optional for edit.', }, - "name": { - "type": "string", - "description": "Skill name in kebab-case (e.g. 'my-skill'). Required for add, optional for edit." + name: { + type: 'string', + description: + "Skill name in kebab-case (e.g. 'my-skill'). Required for add, optional for edit.", }, - "operation": { - "type": "string", - "description": "The operation to perform: 'add', 'edit', 'list', or 'delete'", - "enum": [ - "add", - "edit", - "delete", - "list" - ] + operation: { + type: 'string', + description: "The operation to perform: 'add', 'edit', 'list', or 'delete'", + enum: ['add', 'edit', 'delete', 'list'], + }, + skillId: { + type: 'string', + description: + "The ID of the skill (required for edit/delete). Must be the exact ID from the VFS or list. DO NOT PROVIDE if operation is 'add' or 'list'.", }, - "skillId": { - "type": "string", - "description": "The ID of the skill (required for edit/delete). Must be the exact ID from the VFS or list. DO NOT PROVIDE if operation is 'add' or 'list'." - } }, - "required": [ - "operation" - ] + required: ['operation'], }, resultSchema: undefined, }, - ["materialize_file"]: { + materialize_file: { parameters: { - "type": "object", - "properties": { - "fileName": { - "type": "string", - "description": "The name of the uploaded file to materialize (e.g. \"report.pdf\")" + type: 'object', + properties: { + fileName: { + type: 'string', + description: 'The name of the uploaded file to materialize (e.g. "report.pdf")', }, - "knowledgeBaseId": { - "type": "string", - "description": "ID of an existing knowledge base to add the file to (only used with operation \"knowledge_base\"). If omitted, a new KB is created." + knowledgeBaseId: { + type: 'string', + description: + 'ID of an existing knowledge base to add the file to (only used with operation "knowledge_base"). If omitted, a new KB is created.', }, - "operation": { - "type": "string", - "description": "What to do with the file. \"save\" promotes it to files/. \"import\" imports a workflow JSON. \"table\" converts CSV/TSV/JSON to a table. \"knowledge_base\" saves and adds to a KB. Defaults to \"save\".", - "enum": [ - "save", - "import", - "table", - "knowledge_base" + operation: { + type: 'string', + description: + 'What to do with the file. "save" promotes it to files/. "import" imports a workflow JSON. "table" converts CSV/TSV/JSON to a table. "knowledge_base" saves and adds to a KB. Defaults to "save".', + enum: ['save', 'import', 'table', 'knowledge_base'], + default: 'save', + }, + tableName: { + type: 'string', + description: + 'Custom name for the table (only used with operation "table"). Defaults to the file name without extension.', + }, + }, + required: ['fileName'], + }, + resultSchema: undefined, + }, + move_folder: { + parameters: { + type: 'object', + properties: { + folderId: { + type: 'string', + description: 'The folder ID to move.', + }, + parentId: { + type: 'string', + description: + 'Target parent folder ID. Omit or pass empty string to move to workspace root.', + }, + }, + required: ['folderId'], + }, + resultSchema: undefined, + }, + move_workflow: { + parameters: { + type: 'object', + properties: { + folderId: { + type: 'string', + description: 'Target folder ID. Omit or pass empty string to move to workspace root.', + }, + workflowId: { + type: 'string', + description: 'The workflow ID to move.', + }, + }, + required: ['workflowId'], + }, + resultSchema: undefined, + }, + oauth_get_auth_link: { + parameters: { + type: 'object', + properties: { + providerName: { + type: 'string', + description: + "The name of the OAuth provider to connect (e.g., 'Slack', 'Gmail', 'Google Calendar', 'GitHub')", + }, + }, + required: ['providerName'], + }, + resultSchema: undefined, + }, + oauth_request_access: { + parameters: { + type: 'object', + properties: { + providerName: { + type: 'string', + description: + "The name of the OAuth provider to connect (e.g., 'Slack', 'Gmail', 'Google Calendar')", + }, + }, + required: ['providerName'], + }, + resultSchema: undefined, + }, + open_resource: { + parameters: { + type: 'object', + properties: { + id: { + type: 'string', + description: 'The resource ID to open.', + }, + type: { + type: 'string', + description: 'The resource type to open.', + enum: ['workflow', 'table', 'knowledgebase', 'file'], + }, + }, + required: ['type', 'id'], + }, + resultSchema: undefined, + }, + read: { + parameters: { + type: 'object', + properties: { + limit: { + type: 'number', + description: 'Maximum number of lines to read.', + }, + offset: { + type: 'number', + description: 'Line offset to start reading from (0-indexed).', + }, + outputTable: { + type: 'string', + description: + 'Table ID to import the file contents into (CSV/JSON). All existing rows are replaced. Example: "tbl_abc123"', + }, + path: { + type: 'string', + description: "Path to the file to read (e.g. 'workflows/My Workflow/state.json').", + }, + }, + required: ['path'], + }, + resultSchema: undefined, + }, + redeploy: { + parameters: { + type: 'object', + properties: { + workflowId: { + type: 'string', + description: 'Workflow ID to redeploy (required in workspace context)', + }, + }, + }, + resultSchema: undefined, + }, + rename_workflow: { + parameters: { + type: 'object', + properties: { + name: { + type: 'string', + description: 'The new name for the workflow.', + }, + workflowId: { + type: 'string', + description: 'The workflow ID to rename.', + }, + }, + required: ['workflowId', 'name'], + }, + resultSchema: undefined, + }, + research: { + parameters: { + properties: { + topic: { + description: 'The topic to research.', + type: 'string', + }, + }, + required: ['topic'], + type: 'object', + }, + resultSchema: undefined, + }, + respond: { + parameters: { + additionalProperties: true, + properties: { + output: { + description: + 'The result — facts, status, VFS paths to persisted data, whatever the caller needs to act on.', + type: 'string', + }, + success: { + description: 'Whether the task completed successfully', + type: 'boolean', + }, + type: { + description: 'Optional logical result type override', + type: 'string', + }, + }, + required: ['output', 'success'], + type: 'object', + }, + resultSchema: undefined, + }, + revert_to_version: { + parameters: { + type: 'object', + properties: { + version: { + type: 'number', + description: 'The deployment version number to revert to', + }, + workflowId: { + type: 'string', + description: 'The workflow ID', + }, + }, + required: ['workflowId', 'version'], + }, + resultSchema: undefined, + }, + run: { + parameters: { + properties: { + context: { + description: 'Pre-gathered context: workflow state, block IDs, input requirements.', + type: 'string', + }, + request: { + description: 'What to run or what logs to check.', + type: 'string', + }, + }, + required: ['request'], + type: 'object', + }, + resultSchema: undefined, + }, + run_block: { + parameters: { + type: 'object', + properties: { + blockId: { + type: 'string', + description: 'The block ID to run in isolation.', + }, + executionId: { + type: 'string', + description: + 'Optional execution ID to load the snapshot from. Uses latest execution if omitted.', + }, + useDeployedState: { + type: 'boolean', + description: + 'When true, runs the deployed version instead of the live draft. Default: false (draft).', + }, + workflowId: { + type: 'string', + description: + 'Optional workflow ID to run. If not provided, uses the current workflow in context.', + }, + workflow_input: { + type: 'object', + description: 'JSON object with key-value mappings where each key is an input field name', + }, + }, + required: ['blockId'], + }, + resultSchema: undefined, + }, + run_from_block: { + parameters: { + type: 'object', + properties: { + executionId: { + type: 'string', + description: + 'Optional execution ID to load the snapshot from. Uses latest execution if omitted.', + }, + startBlockId: { + type: 'string', + description: 'The block ID to start execution from.', + }, + useDeployedState: { + type: 'boolean', + description: + 'When true, runs the deployed version instead of the live draft. Default: false (draft).', + }, + workflowId: { + type: 'string', + description: + 'Optional workflow ID to run. If not provided, uses the current workflow in context.', + }, + workflow_input: { + type: 'object', + description: 'JSON object with key-value mappings where each key is an input field name', + }, + }, + required: ['startBlockId'], + }, + resultSchema: undefined, + }, + run_workflow: { + parameters: { + type: 'object', + properties: { + useDeployedState: { + type: 'boolean', + description: + 'When true, runs the deployed version instead of the live draft. Default: false (draft).', + }, + workflowId: { + type: 'string', + description: + 'Optional workflow ID to run. If not provided, uses the current workflow in context.', + }, + workflow_input: { + type: 'object', + description: 'JSON object with key-value mappings where each key is an input field name', + }, + }, + required: ['workflow_input'], + }, + resultSchema: undefined, + }, + run_workflow_until_block: { + parameters: { + type: 'object', + properties: { + stopAfterBlockId: { + type: 'string', + description: 'The block ID to stop after. Execution halts once this block completes.', + }, + useDeployedState: { + type: 'boolean', + description: + 'When true, runs the deployed version instead of the live draft. Default: false (draft).', + }, + workflowId: { + type: 'string', + description: + 'Optional workflow ID to run. If not provided, uses the current workflow in context.', + }, + workflow_input: { + type: 'object', + description: 'JSON object with key-value mappings where each key is an input field name', + }, + }, + required: ['stopAfterBlockId'], + }, + resultSchema: undefined, + }, + scrape_page: { + parameters: { + type: 'object', + properties: { + include_links: { + type: 'boolean', + description: 'Extract all links from the page (default false)', + }, + url: { + type: 'string', + description: 'The URL to scrape (must include https://)', + }, + wait_for: { + type: 'string', + description: 'CSS selector to wait for before scraping (for JS-heavy pages)', + }, + }, + required: ['url'], + }, + resultSchema: undefined, + }, + search_documentation: { + parameters: { + type: 'object', + properties: { + query: { + type: 'string', + description: 'The search query', + }, + topK: { + type: 'number', + description: 'Number of results (max 10)', + }, + }, + required: ['query'], + }, + resultSchema: undefined, + }, + search_library_docs: { + parameters: { + type: 'object', + properties: { + library_name: { + type: 'string', + description: "Name of the library to search for (e.g., 'nextjs', 'stripe', 'langchain')", + }, + query: { + type: 'string', + description: 'The question or topic to find documentation for - be specific', + }, + version: { + type: 'string', + description: "Specific version (optional, e.g., '14', 'v2')", + }, + }, + required: ['library_name', 'query'], + }, + resultSchema: undefined, + }, + search_online: { + parameters: { + type: 'object', + properties: { + category: { + type: 'string', + description: 'Filter by category', + enum: [ + 'news', + 'tweet', + 'github', + 'paper', + 'company', + 'research paper', + 'linkedin profile', + 'pdf', + 'personal site', ], - "default": "save" }, - "tableName": { - "type": "string", - "description": "Custom name for the table (only used with operation \"table\"). Defaults to the file name without extension." - } + include_text: { + type: 'boolean', + description: 'Include page text content (default true)', + }, + num_results: { + type: 'number', + description: 'Number of results (default 10, max 25)', + }, + query: { + type: 'string', + description: 'Natural language search query', + }, }, - "required": [ - "fileName" - ] + required: ['query'], }, resultSchema: undefined, }, - ["move_folder"]: { + search_patterns: { parameters: { - "type": "object", - "properties": { - "folderId": { - "type": "string", - "description": "The folder ID to move." + type: 'object', + properties: { + limit: { + type: 'integer', + description: 'Maximum number of unique pattern examples to return (defaults to 3).', }, - "parentId": { - "type": "string", - "description": "Target parent folder ID. Omit or pass empty string to move to workspace root." - } - }, - "required": [ - "folderId" - ] - }, - resultSchema: undefined, - }, - ["move_workflow"]: { - parameters: { - "type": "object", - "properties": { - "folderId": { - "type": "string", - "description": "Target folder ID. Omit or pass empty string to move to workspace root." - }, - "workflowId": { - "type": "string", - "description": "The workflow ID to move." - } - }, - "required": [ - "workflowId" - ] - }, - resultSchema: undefined, - }, - ["oauth_get_auth_link"]: { - parameters: { - "type": "object", - "properties": { - "providerName": { - "type": "string", - "description": "The name of the OAuth provider to connect (e.g., 'Slack', 'Gmail', 'Google Calendar', 'GitHub')" - } - }, - "required": [ - "providerName" - ] - }, - resultSchema: undefined, - }, - ["oauth_request_access"]: { - parameters: { - "type": "object", - "properties": { - "providerName": { - "type": "string", - "description": "The name of the OAuth provider to connect (e.g., 'Slack', 'Gmail', 'Google Calendar')" - } - }, - "required": [ - "providerName" - ] - }, - resultSchema: undefined, - }, - ["open_resource"]: { - parameters: { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "The resource ID to open." - }, - "type": { - "type": "string", - "description": "The resource type to open.", - "enum": [ - "workflow", - "table", - "knowledgebase", - "file" - ] - } - }, - "required": [ - "type", - "id" - ] - }, - resultSchema: undefined, - }, - ["read"]: { - parameters: { - "type": "object", - "properties": { - "limit": { - "type": "number", - "description": "Maximum number of lines to read." - }, - "offset": { - "type": "number", - "description": "Line offset to start reading from (0-indexed)." - }, - "outputTable": { - "type": "string", - "description": "Table ID to import the file contents into (CSV/JSON). All existing rows are replaced. Example: \"tbl_abc123\"" - }, - "path": { - "type": "string", - "description": "Path to the file to read (e.g. 'workflows/My Workflow/state.json')." - } - }, - "required": [ - "path" - ] - }, - resultSchema: undefined, - }, - ["redeploy"]: { - parameters: { - "type": "object", - "properties": { - "workflowId": { - "type": "string", - "description": "Workflow ID to redeploy (required in workspace context)" - } - } - }, - resultSchema: undefined, - }, - ["rename_workflow"]: { - parameters: { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "The new name for the workflow." - }, - "workflowId": { - "type": "string", - "description": "The workflow ID to rename." - } - }, - "required": [ - "workflowId", - "name" - ] - }, - resultSchema: undefined, - }, - ["research"]: { - parameters: { - "properties": { - "topic": { - "description": "The topic to research.", - "type": "string" - } - }, - "required": [ - "topic" - ], - "type": "object" - }, - resultSchema: undefined, - }, - ["respond"]: { - parameters: { - "additionalProperties": true, - "properties": { - "output": { - "description": "The result — facts, status, VFS paths to persisted data, whatever the caller needs to act on.", - "type": "string" - }, - "success": { - "description": "Whether the task completed successfully", - "type": "boolean" - }, - "type": { - "description": "Optional logical result type override", - "type": "string" - } - }, - "required": [ - "output", - "success" - ], - "type": "object" - }, - resultSchema: undefined, - }, - ["revert_to_version"]: { - parameters: { - "type": "object", - "properties": { - "version": { - "type": "number", - "description": "The deployment version number to revert to" - }, - "workflowId": { - "type": "string", - "description": "The workflow ID" - } - }, - "required": [ - "workflowId", - "version" - ] - }, - resultSchema: undefined, - }, - ["run"]: { - parameters: { - "properties": { - "context": { - "description": "Pre-gathered context: workflow state, block IDs, input requirements.", - "type": "string" - }, - "request": { - "description": "What to run or what logs to check.", - "type": "string" - } - }, - "required": [ - "request" - ], - "type": "object" - }, - resultSchema: undefined, - }, - ["run_block"]: { - parameters: { - "type": "object", - "properties": { - "blockId": { - "type": "string", - "description": "The block ID to run in isolation." - }, - "executionId": { - "type": "string", - "description": "Optional execution ID to load the snapshot from. Uses latest execution if omitted." - }, - "useDeployedState": { - "type": "boolean", - "description": "When true, runs the deployed version instead of the live draft. Default: false (draft)." - }, - "workflowId": { - "type": "string", - "description": "Optional workflow ID to run. If not provided, uses the current workflow in context." - }, - "workflow_input": { - "type": "object", - "description": "JSON object with key-value mappings where each key is an input field name" - } - }, - "required": [ - "blockId" - ] - }, - resultSchema: undefined, - }, - ["run_from_block"]: { - parameters: { - "type": "object", - "properties": { - "executionId": { - "type": "string", - "description": "Optional execution ID to load the snapshot from. Uses latest execution if omitted." - }, - "startBlockId": { - "type": "string", - "description": "The block ID to start execution from." - }, - "useDeployedState": { - "type": "boolean", - "description": "When true, runs the deployed version instead of the live draft. Default: false (draft)." - }, - "workflowId": { - "type": "string", - "description": "Optional workflow ID to run. If not provided, uses the current workflow in context." - }, - "workflow_input": { - "type": "object", - "description": "JSON object with key-value mappings where each key is an input field name" - } - }, - "required": [ - "startBlockId" - ] - }, - resultSchema: undefined, - }, - ["run_workflow"]: { - parameters: { - "type": "object", - "properties": { - "useDeployedState": { - "type": "boolean", - "description": "When true, runs the deployed version instead of the live draft. Default: false (draft)." - }, - "workflowId": { - "type": "string", - "description": "Optional workflow ID to run. If not provided, uses the current workflow in context." - }, - "workflow_input": { - "type": "object", - "description": "JSON object with key-value mappings where each key is an input field name" - } - }, - "required": [ - "workflow_input" - ] - }, - resultSchema: undefined, - }, - ["run_workflow_until_block"]: { - parameters: { - "type": "object", - "properties": { - "stopAfterBlockId": { - "type": "string", - "description": "The block ID to stop after. Execution halts once this block completes." - }, - "useDeployedState": { - "type": "boolean", - "description": "When true, runs the deployed version instead of the live draft. Default: false (draft)." - }, - "workflowId": { - "type": "string", - "description": "Optional workflow ID to run. If not provided, uses the current workflow in context." - }, - "workflow_input": { - "type": "object", - "description": "JSON object with key-value mappings where each key is an input field name" - } - }, - "required": [ - "stopAfterBlockId" - ] - }, - resultSchema: undefined, - }, - ["scrape_page"]: { - parameters: { - "type": "object", - "properties": { - "include_links": { - "type": "boolean", - "description": "Extract all links from the page (default false)" - }, - "url": { - "type": "string", - "description": "The URL to scrape (must include https://)" - }, - "wait_for": { - "type": "string", - "description": "CSS selector to wait for before scraping (for JS-heavy pages)" - } - }, - "required": [ - "url" - ] - }, - resultSchema: undefined, - }, - ["search_documentation"]: { - parameters: { - "type": "object", - "properties": { - "query": { - "type": "string", - "description": "The search query" - }, - "topK": { - "type": "number", - "description": "Number of results (max 10)" - } - }, - "required": [ - "query" - ] - }, - resultSchema: undefined, - }, - ["search_library_docs"]: { - parameters: { - "type": "object", - "properties": { - "library_name": { - "type": "string", - "description": "Name of the library to search for (e.g., 'nextjs', 'stripe', 'langchain')" - }, - "query": { - "type": "string", - "description": "The question or topic to find documentation for - be specific" - }, - "version": { - "type": "string", - "description": "Specific version (optional, e.g., '14', 'v2')" - } - }, - "required": [ - "library_name", - "query" - ] - }, - resultSchema: undefined, - }, - ["search_online"]: { - parameters: { - "type": "object", - "properties": { - "category": { - "type": "string", - "description": "Filter by category", - "enum": [ - "news", - "tweet", - "github", - "paper", - "company", - "research paper", - "linkedin profile", - "pdf", - "personal site" - ] - }, - "include_text": { - "type": "boolean", - "description": "Include page text content (default true)" - }, - "num_results": { - "type": "number", - "description": "Number of results (default 10, max 25)" - }, - "query": { - "type": "string", - "description": "Natural language search query" - } - }, - "required": [ - "query" - ] - }, - resultSchema: undefined, - }, - ["search_patterns"]: { - parameters: { - "type": "object", - "properties": { - "limit": { - "type": "integer", - "description": "Maximum number of unique pattern examples to return (defaults to 3)." - }, - "queries": { - "type": "array", - "description": "Up to 3 descriptive strings explaining the workflow pattern(s) you need. Focus on intent and desired outcomes.", - "items": { - "type": "string", - "description": "Example: \"how to automate wealthbox meeting notes into follow-up tasks\"" - } - } - }, - "required": [ - "queries" - ] - }, - resultSchema: undefined, - }, - ["set_environment_variables"]: { - parameters: { - "type": "object", - "properties": { - "variables": { - "type": "array", - "description": "List of env vars to set", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Variable name" - }, - "value": { - "type": "string", - "description": "Variable value" - } - }, - "required": [ - "name", - "value" - ] - } - } - }, - "required": [ - "variables" - ] - }, - resultSchema: undefined, - }, - ["set_global_workflow_variables"]: { - parameters: { - "type": "object", - "properties": { - "operations": { - "type": "array", - "description": "List of operations to apply", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "operation": { - "type": "string", - "enum": [ - "add", - "delete", - "edit" - ] - }, - "type": { - "type": "string", - "enum": [ - "plain", - "number", - "boolean", - "array", - "object" - ] - }, - "value": { - "type": "string" - } - }, - "required": [ - "operation", - "name", - "type", - "value" - ] - } - }, - "workflowId": { - "type": "string", - "description": "Optional workflow ID. If not provided, uses the current workflow in context." - } - }, - "required": [ - "operations" - ] - }, - resultSchema: undefined, - }, - ["superagent"]: { - parameters: { - "properties": { - "task": { - "description": "A single sentence — the agent has full conversation context. Do NOT pre-read credentials or look up configs. Example: 'send the email we discussed' or 'check my calendar for tomorrow'.", - "type": "string" - } - }, - "required": [ - "task" - ], - "type": "object" - }, - resultSchema: undefined, - }, - ["table"]: { - parameters: { - "properties": { - "request": { - "description": "What table action is needed.", - "type": "string" - } - }, - "required": [ - "request" - ], - "type": "object" - }, - resultSchema: undefined, - }, - ["tool_search_tool_regex"]: { - parameters: { - "properties": { - "case_insensitive": { - "description": "Whether the regex should be case-insensitive (default true).", - "type": "boolean" - }, - "max_results": { - "description": "Maximum number of tools to return (optional).", - "type": "integer" - }, - "pattern": { - "description": "Regular expression to match tool names or descriptions.", - "type": "string" - } - }, - "required": [ - "pattern" - ], - "type": "object" - }, - resultSchema: undefined, - }, - ["update_job_history"]: { - parameters: { - "type": "object", - "properties": { - "jobId": { - "type": "string", - "description": "The job ID." - }, - "summary": { - "type": "string", - "description": "A concise summary of what was done this run (e.g., 'Sent follow-up emails to 3 leads: Alice, Bob, Carol')." - } - }, - "required": [ - "jobId", - "summary" - ] - }, - resultSchema: undefined, - }, - ["update_workspace_mcp_server"]: { - parameters: { - "type": "object", - "properties": { - "description": { - "type": "string", - "description": "New description for the server" - }, - "isPublic": { - "type": "boolean", - "description": "Whether the server is publicly accessible" - }, - "name": { - "type": "string", - "description": "New name for the server" - }, - "serverId": { - "type": "string", - "description": "Required: the MCP server ID to update" - } - }, - "required": [ - "serverId" - ] - }, - resultSchema: undefined, - }, - ["user_memory"]: { - parameters: { - "type": "object", - "properties": { - "confidence": { - "type": "number", - "description": "Confidence level 0-1 (default 1.0 for explicit, 0.8 for inferred)" - }, - "correct_value": { - "type": "string", - "description": "The correct value to replace the wrong one (for 'correct' operation)" - }, - "key": { - "type": "string", - "description": "Unique key for the memory (e.g., 'preferred_model', 'slack_credential')" - }, - "limit": { - "type": "number", - "description": "Number of results for search (default 10)" - }, - "memory_type": { - "type": "string", - "description": "Type of memory: 'preference', 'entity', 'history', or 'correction'", - "enum": [ - "preference", - "entity", - "history", - "correction" - ] - }, - "operation": { - "type": "string", - "description": "Operation: 'add', 'search', 'delete', 'correct', or 'list'", - "enum": [ - "add", - "search", - "delete", - "correct", - "list" - ] - }, - "query": { - "type": "string", - "description": "Search query to find relevant memories" - }, - "source": { - "type": "string", - "description": "Source: 'explicit' (user told you) or 'inferred' (you observed)", - "enum": [ - "explicit", - "inferred" - ] - }, - "value": { - "type": "string", - "description": "Value to remember" - } - }, - "required": [ - "operation" - ] - }, - resultSchema: undefined, - }, - ["user_table"]: { - parameters: { - "type": "object", - "properties": { - "args": { - "type": "object", - "description": "Arguments for the operation", - "properties": { - "column": { - "type": "object", - "description": "Column definition for add_column: { name, type, unique?, position? }" - }, - "columnName": { - "type": "string", - "description": "Column name (required for rename_column, update_column; use columnNames array for batch delete_column)" - }, - "columnNames": { - "type": "array", - "description": "Array of column names to delete at once (for delete_column). Preferred over columnName when deleting multiple columns." - }, - "data": { - "type": "object", - "description": "Row data as key-value pairs (required for insert_row, update_row)" - }, - "description": { - "type": "string", - "description": "Table description (optional for 'create')" - }, - "fileId": { - "type": "string", - "description": "Canonical workspace file ID for create_from_file/import_file. Discover via read(\"files/{name}/meta.json\") or glob(\"files/by-id/*/meta.json\")." - }, - "filePath": { - "type": "string", - "description": "Legacy workspace file reference for create_from_file/import_file. Prefer fileId." - }, - "filter": { - "type": "object", - "description": "MongoDB-style filter for query_rows, update_rows_by_filter, delete_rows_by_filter" - }, - "limit": { - "type": "number", - "description": "Maximum rows to return or affect (optional, default 100)" - }, - "name": { - "type": "string", - "description": "Table name (required for 'create')" - }, - "newName": { - "type": "string", - "description": "New column name (required for rename_column)" - }, - "newType": { - "type": "string", - "description": "New column type (optional for update_column). Types: string, number, boolean, date, json" - }, - "offset": { - "type": "number", - "description": "Number of rows to skip (optional for query_rows, default 0)" - }, - "outputFormat": { - "type": "string", - "description": "Explicit format override for outputPath. Usually unnecessary — the file extension determines the format automatically. Only use this to force a different format than what the extension implies.", - "enum": [ - "json", - "csv", - "txt", - "md", - "html" - ] - }, - "outputPath": { - "type": "string", - "description": "Pipe query_rows results directly to a NEW workspace file. The format is auto-inferred from the file extension: .csv → CSV, .json → JSON, .md → Markdown, etc. Use .csv for tabular exports. Use a flat path like \"files/export.csv\" — nested paths are not supported." - }, - "rowId": { - "type": "string", - "description": "Row ID (required for get_row, update_row, delete_row)" - }, - "rowIds": { - "type": "array", - "description": "Array of row IDs to delete (for batch_delete_rows)" - }, - "rows": { - "type": "array", - "description": "Array of row data objects (required for batch_insert_rows)" - }, - "schema": { - "type": "object", - "description": "Table schema with columns array (required for 'create'). Each column: { name, type, unique? }" - }, - "sort": { - "type": "object", - "description": "Sort specification as { field: 'asc' | 'desc' } (optional for query_rows)" - }, - "tableId": { - "type": "string", - "description": "Table ID (required for most operations except 'create')" - }, - "unique": { - "type": "boolean", - "description": "Set column unique constraint (optional for update_column)" - }, - "updates": { - "type": "array", - "description": "Array of per-row updates: [{ rowId, data: { col: val } }] (for batch_update_rows)" - }, - "values": { - "type": "object", - "description": "Map of rowId to value for single-column batch update: { \"rowId1\": val1, \"rowId2\": val2 } (for batch_update_rows with columnName)" - } - } - }, - "operation": { - "type": "string", - "description": "The operation to perform", - "enum": [ - "create", - "create_from_file", - "import_file", - "get", - "get_schema", - "delete", - "insert_row", - "batch_insert_rows", - "get_row", - "query_rows", - "update_row", - "delete_row", - "update_rows_by_filter", - "delete_rows_by_filter", - "batch_update_rows", - "batch_delete_rows", - "add_column", - "rename_column", - "delete_column", - "update_column" - ] - } - }, - "required": [ - "operation", - "args" - ] - }, - resultSchema: { - "type": "object", - "properties": { - "data": { - "type": "object", - "description": "Operation-specific result payload." - }, - "message": { - "type": "string", - "description": "Human-readable outcome summary." - }, - "success": { - "type": "boolean", - "description": "Whether the operation succeeded." - } - }, - "required": [ - "success", - "message" - ] - }, - }, - ["workflow"]: { - parameters: { - "properties": { - "request": { - "description": "A single sentence — the agent has full conversation context and VFS access. Do NOT look up IDs or pre-read data; the workflow agent does its own research. Example: 'move all the return letter workflows into a folder called Letters'.", - "type": "string" - } - }, - "required": [ - "request" - ], - "type": "object" - }, - resultSchema: undefined, - }, - ["workspace_file"]: { - parameters: { - "type": "object", - "properties": { - "operation": { - "type": "string", - "description": "The file operation to perform.", - "enum": [ - "create", - "append", - "update", - "patch", - "rename", - "delete" - ] - }, - "target": { - "type": "object", - "description": "Explicit file target. Use kind=new_file + fileName for create. Use kind=file_id + fileId for append, update, patch, rename, and delete. Emit target keys in this order: kind, fileId, fileName.", - "properties": { - "kind": { - "type": "string", - "description": "How the file target is identified.", - "enum": [ - "new_file", - "file_id" - ] - }, - "fileId": { - "type": "string", - "description": "Canonical existing workspace file ID. Required when target.kind=file_id." - }, - "fileName": { - "type": "string", - "description": "Plain workspace filename including extension, e.g. \"main.py\" or \"report.docx\". Required when target.kind=new_file." - } + queries: { + type: 'array', + description: + 'Up to 3 descriptive strings explaining the workflow pattern(s) you need. Focus on intent and desired outcomes.', + items: { + type: 'string', + description: 'Example: "how to automate wealthbox meeting notes into follow-up tasks"', }, - "required": [ - "kind" - ] }, - "title": { - "type": "string", - "description": "Optional short UI label for create/append chunks, e.g. \"Chapter 1\" or \"Slide 3\"." - }, - "contentType": { - "type": "string", - "description": "Optional MIME type override. Usually omit and let the system infer from the target file extension.", - "enum": [ - "text/markdown", - "text/html", - "text/plain", - "application/json", - "text/csv", - "application/vnd.openxmlformats-officedocument.presentationml.presentation", - "application/vnd.openxmlformats-officedocument.wordprocessingml.document", - "application/pdf" - ] - }, - "edit": { - "type": "object", - "description": "Patch metadata. Use strategy=search_replace for exact text replacement, or strategy=anchored for line-based inserts/replacements/deletions. Emit edit keys in this order: strategy, search, replace, replaceAll, mode, occurrence, before_anchor, after_anchor, anchor, start_anchor, end_anchor, content.", - "properties": { - "strategy": { - "type": "string", - "description": "Patch strategy.", - "enum": [ - "search_replace", - "anchored" - ] - }, - "search": { - "type": "string", - "description": "Exact text to find when strategy=search_replace. Must match exactly once unless replaceAll=true." - }, - "replace": { - "type": "string", - "description": "Replacement text when strategy=search_replace." - }, - "replaceAll": { - "type": "boolean", - "description": "When true and strategy=search_replace, replace every match instead of requiring a unique single match." - }, - "mode": { - "type": "string", - "description": "Anchored edit mode when strategy=anchored.", - "enum": [ - "replace_between", - "insert_after", - "delete_between" - ] - }, - "occurrence": { - "type": "number", - "description": "1-based occurrence for repeated anchor lines. Optional; defaults to 1." - }, - "before_anchor": { - "type": "string", - "description": "Boundary line kept before inserted replacement content. Required for mode=replace_between." - }, - "after_anchor": { - "type": "string", - "description": "Boundary line kept after inserted replacement content. Required for mode=replace_between." - }, - "anchor": { - "type": "string", - "description": "Anchor line after which new content is inserted. Required for mode=insert_after." - }, - "start_anchor": { - "type": "string", - "description": "First line to delete. Required for mode=delete_between." - }, - "end_anchor": { - "type": "string", - "description": "First line to keep after deletion. Required for mode=delete_between." - }, - "content": { - "type": "string", - "description": "Inserted or replacement content for anchored edits. Not used for delete_between." - } - } - }, - "newName": { - "type": "string", - "description": "New file name for rename. Must be a plain workspace filename like \"main.py\"." - }, - "content": { - "type": "string", - "description": "File content for create, append, or update. For .pptx/.docx/.pdf this must be JavaScript source code for the corresponding generator runtime." - } }, - "required": [ - "operation", - "target" - ] + required: ['queries'], + }, + resultSchema: undefined, + }, + set_environment_variables: { + parameters: { + type: 'object', + properties: { + variables: { + type: 'array', + description: 'List of env vars to set', + items: { + type: 'object', + properties: { + name: { + type: 'string', + description: 'Variable name', + }, + value: { + type: 'string', + description: 'Variable value', + }, + }, + required: ['name', 'value'], + }, + }, + }, + required: ['variables'], + }, + resultSchema: undefined, + }, + set_global_workflow_variables: { + parameters: { + type: 'object', + properties: { + operations: { + type: 'array', + description: 'List of operations to apply', + items: { + type: 'object', + properties: { + name: { + type: 'string', + }, + operation: { + type: 'string', + enum: ['add', 'delete', 'edit'], + }, + type: { + type: 'string', + enum: ['plain', 'number', 'boolean', 'array', 'object'], + }, + value: { + type: 'string', + }, + }, + required: ['operation', 'name', 'type', 'value'], + }, + }, + workflowId: { + type: 'string', + description: + 'Optional workflow ID. If not provided, uses the current workflow in context.', + }, + }, + required: ['operations'], + }, + resultSchema: undefined, + }, + superagent: { + parameters: { + properties: { + task: { + description: + "A single sentence — the agent has full conversation context. Do NOT pre-read credentials or look up configs. Example: 'send the email we discussed' or 'check my calendar for tomorrow'.", + type: 'string', + }, + }, + required: ['task'], + type: 'object', + }, + resultSchema: undefined, + }, + table: { + parameters: { + properties: { + request: { + description: 'What table action is needed.', + type: 'string', + }, + }, + required: ['request'], + type: 'object', + }, + resultSchema: undefined, + }, + tool_search_tool_regex: { + parameters: { + properties: { + case_insensitive: { + description: 'Whether the regex should be case-insensitive (default true).', + type: 'boolean', + }, + max_results: { + description: 'Maximum number of tools to return (optional).', + type: 'integer', + }, + pattern: { + description: 'Regular expression to match tool names or descriptions.', + type: 'string', + }, + }, + required: ['pattern'], + type: 'object', + }, + resultSchema: undefined, + }, + update_job_history: { + parameters: { + type: 'object', + properties: { + jobId: { + type: 'string', + description: 'The job ID.', + }, + summary: { + type: 'string', + description: + "A concise summary of what was done this run (e.g., 'Sent follow-up emails to 3 leads: Alice, Bob, Carol').", + }, + }, + required: ['jobId', 'summary'], + }, + resultSchema: undefined, + }, + update_workspace_mcp_server: { + parameters: { + type: 'object', + properties: { + description: { + type: 'string', + description: 'New description for the server', + }, + isPublic: { + type: 'boolean', + description: 'Whether the server is publicly accessible', + }, + name: { + type: 'string', + description: 'New name for the server', + }, + serverId: { + type: 'string', + description: 'Required: the MCP server ID to update', + }, + }, + required: ['serverId'], + }, + resultSchema: undefined, + }, + user_memory: { + parameters: { + type: 'object', + properties: { + confidence: { + type: 'number', + description: 'Confidence level 0-1 (default 1.0 for explicit, 0.8 for inferred)', + }, + correct_value: { + type: 'string', + description: "The correct value to replace the wrong one (for 'correct' operation)", + }, + key: { + type: 'string', + description: "Unique key for the memory (e.g., 'preferred_model', 'slack_credential')", + }, + limit: { + type: 'number', + description: 'Number of results for search (default 10)', + }, + memory_type: { + type: 'string', + description: "Type of memory: 'preference', 'entity', 'history', or 'correction'", + enum: ['preference', 'entity', 'history', 'correction'], + }, + operation: { + type: 'string', + description: "Operation: 'add', 'search', 'delete', 'correct', or 'list'", + enum: ['add', 'search', 'delete', 'correct', 'list'], + }, + query: { + type: 'string', + description: 'Search query to find relevant memories', + }, + source: { + type: 'string', + description: "Source: 'explicit' (user told you) or 'inferred' (you observed)", + enum: ['explicit', 'inferred'], + }, + value: { + type: 'string', + description: 'Value to remember', + }, + }, + required: ['operation'], + }, + resultSchema: undefined, + }, + user_table: { + parameters: { + type: 'object', + properties: { + args: { + type: 'object', + description: 'Arguments for the operation', + properties: { + column: { + type: 'object', + description: 'Column definition for add_column: { name, type, unique?, position? }', + }, + columnName: { + type: 'string', + description: + 'Column name (required for rename_column, update_column; use columnNames array for batch delete_column)', + }, + columnNames: { + type: 'array', + description: + 'Array of column names to delete at once (for delete_column). Preferred over columnName when deleting multiple columns.', + }, + data: { + type: 'object', + description: 'Row data as key-value pairs (required for insert_row, update_row)', + }, + description: { + type: 'string', + description: "Table description (optional for 'create')", + }, + fileId: { + type: 'string', + description: + 'Canonical workspace file ID for create_from_file/import_file. Discover via read("files/{name}/meta.json") or glob("files/by-id/*/meta.json").', + }, + filePath: { + type: 'string', + description: + 'Legacy workspace file reference for create_from_file/import_file. Prefer fileId.', + }, + filter: { + type: 'object', + description: + 'MongoDB-style filter for query_rows, update_rows_by_filter, delete_rows_by_filter', + }, + limit: { + type: 'number', + description: 'Maximum rows to return or affect (optional, default 100)', + }, + name: { + type: 'string', + description: "Table name (required for 'create')", + }, + newName: { + type: 'string', + description: 'New column name (required for rename_column)', + }, + newType: { + type: 'string', + description: + 'New column type (optional for update_column). Types: string, number, boolean, date, json', + }, + offset: { + type: 'number', + description: 'Number of rows to skip (optional for query_rows, default 0)', + }, + outputFormat: { + type: 'string', + description: + 'Explicit format override for outputPath. Usually unnecessary — the file extension determines the format automatically. Only use this to force a different format than what the extension implies.', + enum: ['json', 'csv', 'txt', 'md', 'html'], + }, + outputPath: { + type: 'string', + description: + 'Pipe query_rows results directly to a NEW workspace file. The format is auto-inferred from the file extension: .csv → CSV, .json → JSON, .md → Markdown, etc. Use .csv for tabular exports. Use a flat path like "files/export.csv" — nested paths are not supported.', + }, + rowId: { + type: 'string', + description: 'Row ID (required for get_row, update_row, delete_row)', + }, + rowIds: { + type: 'array', + description: 'Array of row IDs to delete (for batch_delete_rows)', + }, + rows: { + type: 'array', + description: 'Array of row data objects (required for batch_insert_rows)', + }, + schema: { + type: 'object', + description: + "Table schema with columns array (required for 'create'). Each column: { name, type, unique? }", + }, + sort: { + type: 'object', + description: + "Sort specification as { field: 'asc' | 'desc' } (optional for query_rows)", + }, + tableId: { + type: 'string', + description: "Table ID (required for most operations except 'create')", + }, + unique: { + type: 'boolean', + description: 'Set column unique constraint (optional for update_column)', + }, + updates: { + type: 'array', + description: + 'Array of per-row updates: [{ rowId, data: { col: val } }] (for batch_update_rows)', + }, + values: { + type: 'object', + description: + 'Map of rowId to value for single-column batch update: { "rowId1": val1, "rowId2": val2 } (for batch_update_rows with columnName)', + }, + }, + }, + operation: { + type: 'string', + description: 'The operation to perform', + enum: [ + 'create', + 'create_from_file', + 'import_file', + 'get', + 'get_schema', + 'delete', + 'insert_row', + 'batch_insert_rows', + 'get_row', + 'query_rows', + 'update_row', + 'delete_row', + 'update_rows_by_filter', + 'delete_rows_by_filter', + 'batch_update_rows', + 'batch_delete_rows', + 'add_column', + 'rename_column', + 'delete_column', + 'update_column', + ], + }, + }, + required: ['operation', 'args'], }, resultSchema: { - "type": "object", - "properties": { - "data": { - "type": "object", - "description": "Optional operation metadata such as file id, file name, size, and content type." + type: 'object', + properties: { + data: { + type: 'object', + description: 'Operation-specific result payload.', }, - "message": { - "type": "string", - "description": "Human-readable summary of the outcome." + message: { + type: 'string', + description: 'Human-readable outcome summary.', + }, + success: { + type: 'boolean', + description: 'Whether the operation succeeded.', }, - "success": { - "type": "boolean", - "description": "Whether the file operation succeeded." - } }, - "required": [ - "success", - "message" - ] + required: ['success', 'message'], + }, + }, + workflow: { + parameters: { + properties: { + request: { + description: + "A single sentence — the agent has full conversation context and VFS access. Do NOT look up IDs or pre-read data; the workflow agent does its own research. Example: 'move all the return letter workflows into a folder called Letters'.", + type: 'string', + }, + }, + required: ['request'], + type: 'object', + }, + resultSchema: undefined, + }, + workspace_file: { + parameters: { + type: 'object', + properties: { + operation: { + type: 'string', + description: 'The file operation to perform.', + enum: ['create', 'append', 'update', 'patch', 'rename', 'delete'], + }, + target: { + type: 'object', + description: + 'Explicit file target. Use kind=new_file + fileName for create. Use kind=file_id + fileId for append, update, patch, rename, and delete. Emit target keys in this order: kind, fileId, fileName.', + properties: { + kind: { + type: 'string', + description: 'How the file target is identified.', + enum: ['new_file', 'file_id'], + }, + fileId: { + type: 'string', + description: + 'Canonical existing workspace file ID. Required when target.kind=file_id.', + }, + fileName: { + type: 'string', + description: + 'Plain workspace filename including extension, e.g. "main.py" or "report.docx". Required when target.kind=new_file.', + }, + }, + required: ['kind'], + }, + title: { + type: 'string', + description: + 'Optional short UI label for create/append chunks, e.g. "Chapter 1" or "Slide 3".', + }, + contentType: { + type: 'string', + description: + 'Optional MIME type override. Usually omit and let the system infer from the target file extension.', + enum: [ + 'text/markdown', + 'text/html', + 'text/plain', + 'application/json', + 'text/csv', + 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'application/pdf', + ], + }, + edit: { + type: 'object', + description: + 'Patch metadata. Use strategy=search_replace for exact text replacement, or strategy=anchored for line-based inserts/replacements/deletions. Emit edit keys in this order: strategy, search, replace, replaceAll, mode, occurrence, before_anchor, after_anchor, anchor, start_anchor, end_anchor, content.', + properties: { + strategy: { + type: 'string', + description: 'Patch strategy.', + enum: ['search_replace', 'anchored'], + }, + search: { + type: 'string', + description: + 'Exact text to find when strategy=search_replace. Must match exactly once unless replaceAll=true.', + }, + replace: { + type: 'string', + description: 'Replacement text when strategy=search_replace.', + }, + replaceAll: { + type: 'boolean', + description: + 'When true and strategy=search_replace, replace every match instead of requiring a unique single match.', + }, + mode: { + type: 'string', + description: 'Anchored edit mode when strategy=anchored.', + enum: ['replace_between', 'insert_after', 'delete_between'], + }, + occurrence: { + type: 'number', + description: '1-based occurrence for repeated anchor lines. Optional; defaults to 1.', + }, + before_anchor: { + type: 'string', + description: + 'Boundary line kept before inserted replacement content. Required for mode=replace_between.', + }, + after_anchor: { + type: 'string', + description: + 'Boundary line kept after inserted replacement content. Required for mode=replace_between.', + }, + anchor: { + type: 'string', + description: + 'Anchor line after which new content is inserted. Required for mode=insert_after.', + }, + start_anchor: { + type: 'string', + description: 'First line to delete. Required for mode=delete_between.', + }, + end_anchor: { + type: 'string', + description: 'First line to keep after deletion. Required for mode=delete_between.', + }, + content: { + type: 'string', + description: + 'Inserted or replacement content for anchored edits. Not used for delete_between.', + }, + }, + }, + newName: { + type: 'string', + description: + 'New file name for rename. Must be a plain workspace filename like "main.py".', + }, + content: { + type: 'string', + description: + 'File content for create, append, or update. For .pptx/.docx/.pdf this must be JavaScript source code for the corresponding generator runtime.', + }, + }, + required: ['operation', 'target'], + }, + resultSchema: { + type: 'object', + properties: { + data: { + type: 'object', + description: + 'Optional operation metadata such as file id, file name, size, and content type.', + }, + message: { + type: 'string', + description: 'Human-readable summary of the outcome.', + }, + success: { + type: 'boolean', + description: 'Whether the file operation succeeded.', + }, + }, + required: ['success', 'message'], }, }, } diff --git a/apps/sim/lib/copilot/request/go/stream.ts b/apps/sim/lib/copilot/request/go/stream.ts index bce8fe9bd0..10fd7b09e4 100644 --- a/apps/sim/lib/copilot/request/go/stream.ts +++ b/apps/sim/lib/copilot/request/go/stream.ts @@ -32,7 +32,7 @@ type FilePreviewServerState = { title?: string editMetaKey?: string targetKey?: string - emittedContentLength: number + lastContentSnapshot?: string } function extractJsonString(raw: string, key: string): string | undefined { @@ -74,6 +74,70 @@ function extractJsonNumber(raw: string, key: string): number | undefined { return Number.parseInt(match[1], 10) } +function decodeJsonStringPrefix(input: string): string { + let output = '' + for (let i = 0; i < input.length; i++) { + const ch = input[i] + if (ch !== '\\') { + output += ch + continue + } + const next = input[i + 1] + if (!next) break + if (next === 'n') { + output += '\n' + i++ + continue + } + if (next === 't') { + output += '\t' + i++ + continue + } + if (next === 'r') { + output += '\r' + i++ + continue + } + if (next === '"') { + output += '"' + i++ + continue + } + if (next === '\\') { + output += '\\' + i++ + continue + } + if (next === '/') { + output += '/' + i++ + continue + } + if (next === 'b') { + output += '\b' + i++ + continue + } + if (next === 'f') { + output += '\f' + i++ + continue + } + if (next === 'u') { + const hex = input.slice(i + 2, i + 6) + if (hex.length < 4 || !/^[0-9a-fA-F]{4}$/.test(hex)) { + break + } + output += String.fromCharCode(Number.parseInt(hex, 16)) + i += 5 + continue + } + break + } + return output +} + function extractStreamedContent(raw: string, preferredKey: 'content' | 'replace'): string { const marker = `"${preferredKey}":` const idx = raw.indexOf(marker) @@ -92,13 +156,7 @@ function extractStreamedContent(raw: string, preferredKey: 'content' | 'replace' } } const inner = end === -1 ? rest.slice(1) : rest.slice(1, end) - return inner - .replace(/\\n/g, '\n') - .replace(/\\t/g, '\t') - .replace(/\\r/g, '\r') - .replace(/\\"/g, '"') - .replace(/\\u([0-9a-fA-F]{4})/g, (_, hex) => String.fromCharCode(Number.parseInt(hex, 16))) - .replace(/\\\\/g, '\\') + return decodeJsonStringPrefix(inner) } function buildPreviewContent(raw: string, strategy?: string): string { @@ -235,7 +293,6 @@ export async function runStreamLoop( const state = filePreviewState.get(toolCallId) ?? { raw: '', started: false, - emittedContentLength: 0, } state.raw += delta @@ -343,16 +400,15 @@ export async function runStreamLoop( } const streamedContent = buildPreviewContent(state.raw, strategy) - if (streamedContent.length > state.emittedContentLength) { - const contentDelta = streamedContent.slice(state.emittedContentLength) - state.emittedContentLength = streamedContent.length + if (streamedContent !== (state.lastContentSnapshot ?? '')) { + state.lastContentSnapshot = streamedContent await options.onEvent?.({ type: MothershipStreamV1EventType.tool, payload: { toolCallId, toolName: 'workspace_file', - previewPhase: 'file_preview_content_delta', - delta: contentDelta, + previewPhase: 'file_preview_content', + content: streamedContent, }, ...(streamEvent.scope ? { scope: streamEvent.scope } : {}), }) diff --git a/apps/sim/lib/copilot/request/handlers/tool.ts b/apps/sim/lib/copilot/request/handlers/tool.ts index e5d50743c3..6c9a1cc4f6 100644 --- a/apps/sim/lib/copilot/request/handlers/tool.ts +++ b/apps/sim/lib/copilot/request/handlers/tool.ts @@ -21,7 +21,7 @@ import type { StreamingContext, ToolCallState, } from '@/lib/copilot/request/types' -import { isSimExecuted, getToolEntry } from '@/lib/copilot/tool-executor' +import { getToolEntry, isSimExecuted } from '@/lib/copilot/tool-executor' import { isWorkflowToolName } from '@/lib/copilot/tools/workflow-tools' import type { ToolScope } from './types' import { diff --git a/apps/sim/lib/copilot/resources/extraction.ts b/apps/sim/lib/copilot/resources/extraction.ts index 2c9fdf7015..e1f8caff55 100644 --- a/apps/sim/lib/copilot/resources/extraction.ts +++ b/apps/sim/lib/copilot/resources/extraction.ts @@ -42,7 +42,9 @@ function getOperation(params: Record | undefined): string | und return (args.operation ?? params?.operation) as string | undefined } -function getWorkspaceFileTarget(params: Record | undefined): Record { +function getWorkspaceFileTarget( + params: Record | undefined +): Record { return asRecord(params?.target) } @@ -255,10 +257,7 @@ export function extractDeletedResourcesFromToolResult( case WorkspaceFile.id: { if (operation !== 'delete') return [] const target = getWorkspaceFileTarget(params) - const fileId = - (data.id as string) ?? - (target.fileId as string) ?? - (args.fileId as string) + const fileId = (data.id as string) ?? (target.fileId as string) ?? (args.fileId as string) if (fileId) { return [{ type: resourceType, id: fileId, title: (data.name as string) || 'File' }] } diff --git a/apps/sim/lib/copilot/tools/server/files/workspace-file.ts b/apps/sim/lib/copilot/tools/server/files/workspace-file.ts index e1d7a2baa6..1805c98a2d 100644 --- a/apps/sim/lib/copilot/tools/server/files/workspace-file.ts +++ b/apps/sim/lib/copilot/tools/server/files/workspace-file.ts @@ -70,8 +70,6 @@ type WorkspaceFileArgs = { contentType?: string newName?: string edit?: WorkspaceFileEdit - // Legacy nested shape kept temporarily for compatibility during migration. - args?: Record } type WorkspaceFileResult = { @@ -140,102 +138,6 @@ function getDocumentFormatInfo(fileName: string): { return { isDoc: false } } -function normalizeWorkspaceFileParams(params: WorkspaceFileArgs): { - operation: WorkspaceFileOperation - target?: WorkspaceFileTarget - title?: string - content?: string - contentType?: string - newName?: string - edit?: WorkspaceFileEdit -} { - if (params.target || params.edit || params.content !== undefined || params.newName !== undefined) { - return { - operation: params.operation, - target: params.target, - title: params.title, - content: params.content, - contentType: params.contentType, - newName: params.newName, - edit: params.edit, - } - } - - const legacyArgs = (params.args ?? {}) as Record - const legacyOperation = params.operation - const legacyTarget: WorkspaceFileTarget | undefined = - legacyOperation === 'create' - ? ({ - kind: 'new_file', - fileName: String(legacyArgs.fileName ?? ''), - } as WorkspaceFileTarget) - : legacyArgs.fileId - ? ({ - kind: 'file_id', - fileId: String(legacyArgs.fileId), - ...(legacyArgs.fileName ? { fileName: String(legacyArgs.fileName) } : {}), - } as WorkspaceFileTarget) - : legacyArgs.fileName - ? ({ - kind: 'new_file', - fileName: String(legacyArgs.fileName), - } as WorkspaceFileTarget) - : undefined - - const legacyEdit = (() => { - const structured = legacyArgs.edit as Record | undefined - if (structured && typeof structured.mode === 'string') { - return { - strategy: 'anchored', - mode: structured.mode as 'replace_between' | 'insert_after' | 'delete_between', - occurrence: - typeof structured.occurrence === 'number' ? structured.occurrence : undefined, - before_anchor: - typeof structured.before_anchor === 'string' ? structured.before_anchor : undefined, - after_anchor: - typeof structured.after_anchor === 'string' ? structured.after_anchor : undefined, - start_anchor: - typeof structured.start_anchor === 'string' ? structured.start_anchor : undefined, - end_anchor: - typeof structured.end_anchor === 'string' ? structured.end_anchor : undefined, - anchor: typeof structured.anchor === 'string' ? structured.anchor : undefined, - content: typeof structured.content === 'string' ? structured.content : undefined, - } satisfies WorkspaceFileEdit - } - - const edits = legacyArgs.edits as Array<{ search?: unknown; replace?: unknown }> | undefined - if (Array.isArray(edits) && edits.length > 0) { - const first = edits[0] - if (typeof first?.search === 'string' && typeof first?.replace === 'string') { - return { - strategy: 'search_replace', - search: first.search, - replace: first.replace, - } satisfies WorkspaceFileEdit - } - } - - return undefined - })() - - const normalizedOperation: WorkspaceFileOperation = - (legacyOperation as string) === 'write' - ? legacyTarget?.kind === 'new_file' - ? 'create' - : 'append' - : (legacyOperation as WorkspaceFileOperation) - - return { - operation: normalizedOperation, - target: legacyTarget, - title: typeof legacyArgs.title === 'string' ? legacyArgs.title : undefined, - content: typeof legacyArgs.content === 'string' ? legacyArgs.content : undefined, - contentType: typeof legacyArgs.contentType === 'string' ? legacyArgs.contentType : undefined, - newName: typeof legacyArgs.newName === 'string' ? legacyArgs.newName : undefined, - edit: legacyEdit, - } -} - export const workspaceFileServerTool: BaseServerTool = { name: WorkspaceFile.id, async execute( @@ -250,7 +152,7 @@ export const workspaceFileServerTool: BaseServerTool