mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
feat(integrations): added deeper integrations for slack, supabase, firecrawl, exa, notion (#728)
* added deeper exa integrations * added firecrawl crawl tool * include (optional) indicator for fields that are not explicitly required to be filled in by the user * use aliased imports, stronger typing, added additional notion tools * added additional notion tools, tested * added additional supabase tools, updated CSP * added remaining supabase tools * finished supabase tools * fixed persistence of selector inputs on refresh, added supabase tools and slack tools * fixed failing test * remove unrelated file
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
export async function GET(
|
||||
request: NextRequest,
|
||||
{ params }: { params: Promise<{ jobId: string }> }
|
||||
) {
|
||||
const { jobId } = await params
|
||||
const authHeader = request.headers.get('authorization')
|
||||
|
||||
if (!authHeader) {
|
||||
return NextResponse.json({ error: 'Authorization header is required' }, { status: 401 })
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`https://api.firecrawl.dev/v1/crawl/${jobId}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Authorization: authHeader,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
return NextResponse.json(
|
||||
{ error: data.error || data.message || 'Failed to get crawl status' },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
return NextResponse.json(data)
|
||||
} catch (error: any) {
|
||||
return NextResponse.json(
|
||||
{ error: `Failed to fetch crawl status: ${error.message}` },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
+9
-5
@@ -4,6 +4,7 @@ import { useEffect, useState } from 'react'
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
|
||||
import type { SubBlockConfig } from '@/blocks/types'
|
||||
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
|
||||
import { useSubBlockValue } from '../../hooks/use-sub-block-value'
|
||||
import { type SlackChannelInfo, SlackChannelSelector } from './components/slack-channel-selector'
|
||||
|
||||
interface ChannelSelectorInputProps {
|
||||
@@ -25,7 +26,10 @@ export function ChannelSelectorInput({
|
||||
isPreview = false,
|
||||
previewValue,
|
||||
}: ChannelSelectorInputProps) {
|
||||
const { getValue, setValue } = useSubBlockStore()
|
||||
const { getValue } = useSubBlockStore()
|
||||
|
||||
// Use the proper hook to get the current value and setter (same as file-selector)
|
||||
const [storeValue, setStoreValue] = useSubBlockValue(blockId, subBlock.id)
|
||||
const [selectedChannelId, setSelectedChannelId] = useState<string>('')
|
||||
const [_channelInfo, setChannelInfo] = useState<SlackChannelInfo | null>(null)
|
||||
|
||||
@@ -47,9 +51,9 @@ export function ChannelSelectorInput({
|
||||
}
|
||||
|
||||
// Use preview value when in preview mode, otherwise use store value
|
||||
const value = isPreview ? previewValue : getValue(blockId, subBlock.id)
|
||||
const value = isPreview ? previewValue : storeValue
|
||||
|
||||
// Get the current value from the store or prop value if in preview mode
|
||||
// Get the current value from the store or prop value if in preview mode (same pattern as file-selector)
|
||||
useEffect(() => {
|
||||
if (isPreview && previewValue !== undefined) {
|
||||
const value = previewValue
|
||||
@@ -64,12 +68,12 @@ export function ChannelSelectorInput({
|
||||
}
|
||||
}, [blockId, subBlock.id, getValue, isPreview, previewValue])
|
||||
|
||||
// Handle channel selection
|
||||
// Handle channel selection (same pattern as file-selector)
|
||||
const handleChannelChange = (channelId: string, info?: SlackChannelInfo) => {
|
||||
setSelectedChannelId(channelId)
|
||||
setChannelInfo(info || null)
|
||||
if (!isPreview) {
|
||||
setValue(blockId, subBlock.id, channelId)
|
||||
setStoreValue(channelId)
|
||||
}
|
||||
onChannelSelect?.(channelId)
|
||||
}
|
||||
|
||||
+9
-9
@@ -107,15 +107,15 @@ const SCOPE_DESCRIPTIONS: Record<string, string> = {
|
||||
'guilds.members.read': 'Read your Discord guild members',
|
||||
read: 'Read access to your workspace',
|
||||
write: 'Write access to your Linear workspace',
|
||||
'channels:read': 'Read your Slack channels',
|
||||
'groups:read': 'Read your Slack private channels',
|
||||
'chat:write': 'Write to your invited Slack channels',
|
||||
'chat:write.public': 'Write to your public Slack channels',
|
||||
'users:read': 'Read your Slack users',
|
||||
'search:read': 'Read your Slack search',
|
||||
'files:read': 'Read your Slack files',
|
||||
'links:read': 'Read your Slack links',
|
||||
'links:write': 'Write to your Slack links',
|
||||
'channels:read': 'View public channels',
|
||||
'channels:history': 'Read channel messages',
|
||||
'groups:read': 'View private channels',
|
||||
'groups:history': 'Read private messages',
|
||||
'chat:write': 'Send messages',
|
||||
'chat:write.public': 'Post to public channels',
|
||||
'users:read': 'View workspace users',
|
||||
'files:write': 'Upload files',
|
||||
'canvases:write': 'Create canvas documents',
|
||||
}
|
||||
|
||||
// Convert OAuth scope to user-friendly description
|
||||
|
||||
+5
-5
@@ -1006,9 +1006,9 @@ export function ToolInput({
|
||||
case 'channel-selector':
|
||||
return (
|
||||
<ChannelSelectorInput
|
||||
blockId={uniqueBlockId}
|
||||
blockId={blockId}
|
||||
subBlock={{
|
||||
id: param.id,
|
||||
id: `tool-${toolIndex || 0}-${param.id}`,
|
||||
type: 'channel-selector' as const,
|
||||
title: param.id,
|
||||
provider: uiComponent.provider || 'slack',
|
||||
@@ -1023,9 +1023,9 @@ export function ToolInput({
|
||||
case 'project-selector':
|
||||
return (
|
||||
<ProjectSelectorInput
|
||||
blockId={uniqueBlockId}
|
||||
blockId={blockId}
|
||||
subBlock={{
|
||||
id: param.id,
|
||||
id: `tool-${toolIndex || 0}-${param.id}`,
|
||||
type: 'project-selector' as const,
|
||||
title: param.id,
|
||||
provider: uiComponent.provider || 'jira',
|
||||
@@ -1632,7 +1632,7 @@ export function ToolInput({
|
||||
{param.required && param.visibility === 'user-only' && (
|
||||
<span className='ml-1 text-red-500'>*</span>
|
||||
)}
|
||||
{!param.required && (
|
||||
{(!param.required || param.visibility !== 'user-only') && (
|
||||
<span className='ml-1 text-muted-foreground/60 text-xs'>
|
||||
(Optional)
|
||||
</span>
|
||||
|
||||
@@ -896,4 +896,4 @@ export function SearchModal({
|
||||
</DialogPortal>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@ export const ExaBlock: BlockConfig<ExaResponse> = {
|
||||
bgColor: '#1F40ED',
|
||||
icon: ExaAIIcon,
|
||||
subBlocks: [
|
||||
// Operation selector
|
||||
{
|
||||
id: 'operation',
|
||||
title: 'Operation',
|
||||
@@ -24,6 +23,7 @@ export const ExaBlock: BlockConfig<ExaResponse> = {
|
||||
{ label: 'Get Contents', id: 'exa_get_contents' },
|
||||
{ label: 'Find Similar Links', id: 'exa_find_similar_links' },
|
||||
{ label: 'Answer', id: 'exa_answer' },
|
||||
{ label: 'Research', id: 'exa_research' },
|
||||
],
|
||||
value: () => 'exa_search',
|
||||
},
|
||||
@@ -129,6 +129,22 @@ export const ExaBlock: BlockConfig<ExaResponse> = {
|
||||
layout: 'full',
|
||||
condition: { field: 'operation', value: 'exa_answer' },
|
||||
},
|
||||
// Research operation inputs
|
||||
{
|
||||
id: 'query',
|
||||
title: 'Research Query',
|
||||
type: 'long-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Enter your research topic or question...',
|
||||
condition: { field: 'operation', value: 'exa_research' },
|
||||
},
|
||||
{
|
||||
id: 'includeText',
|
||||
title: 'Include Full Text',
|
||||
type: 'switch',
|
||||
layout: 'full',
|
||||
condition: { field: 'operation', value: 'exa_research' },
|
||||
},
|
||||
// API Key (common)
|
||||
{
|
||||
id: 'apiKey',
|
||||
@@ -140,7 +156,13 @@ export const ExaBlock: BlockConfig<ExaResponse> = {
|
||||
},
|
||||
],
|
||||
tools: {
|
||||
access: ['exa_search', 'exa_get_contents', 'exa_find_similar_links', 'exa_answer'],
|
||||
access: [
|
||||
'exa_search',
|
||||
'exa_get_contents',
|
||||
'exa_find_similar_links',
|
||||
'exa_answer',
|
||||
'exa_research',
|
||||
],
|
||||
config: {
|
||||
tool: (params) => {
|
||||
// Convert numResults to a number for operations that use it
|
||||
@@ -157,6 +179,8 @@ export const ExaBlock: BlockConfig<ExaResponse> = {
|
||||
return 'exa_find_similar_links'
|
||||
case 'exa_answer':
|
||||
return 'exa_answer'
|
||||
case 'exa_research':
|
||||
return 'exa_research'
|
||||
default:
|
||||
return 'exa_search'
|
||||
}
|
||||
@@ -186,5 +210,7 @@ export const ExaBlock: BlockConfig<ExaResponse> = {
|
||||
// Answer output
|
||||
answer: 'string',
|
||||
citations: 'json',
|
||||
// Research output
|
||||
research: 'json',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ export const FirecrawlBlock: BlockConfig<FirecrawlResponse> = {
|
||||
options: [
|
||||
{ label: 'Scrape', id: 'scrape' },
|
||||
{ label: 'Search', id: 'search' },
|
||||
{ label: 'Crawl', id: 'crawl' },
|
||||
],
|
||||
value: () => 'scrape',
|
||||
},
|
||||
@@ -29,10 +30,10 @@ export const FirecrawlBlock: BlockConfig<FirecrawlResponse> = {
|
||||
title: 'Website URL',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Enter the webpage URL to scrape',
|
||||
placeholder: 'Enter the website URL',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'scrape',
|
||||
value: ['scrape', 'crawl'],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -45,6 +46,17 @@ export const FirecrawlBlock: BlockConfig<FirecrawlResponse> = {
|
||||
value: 'scrape',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'limit',
|
||||
title: 'Page Limit',
|
||||
type: 'short-input',
|
||||
layout: 'half',
|
||||
placeholder: '100',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'crawl',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'query',
|
||||
title: 'Search Query',
|
||||
@@ -66,7 +78,7 @@ export const FirecrawlBlock: BlockConfig<FirecrawlResponse> = {
|
||||
},
|
||||
],
|
||||
tools: {
|
||||
access: ['firecrawl_scrape', 'firecrawl_search'],
|
||||
access: ['firecrawl_scrape', 'firecrawl_search', 'firecrawl_crawl'],
|
||||
config: {
|
||||
tool: (params) => {
|
||||
switch (params.operation) {
|
||||
@@ -74,16 +86,32 @@ export const FirecrawlBlock: BlockConfig<FirecrawlResponse> = {
|
||||
return 'firecrawl_scrape'
|
||||
case 'search':
|
||||
return 'firecrawl_search'
|
||||
case 'crawl':
|
||||
return 'firecrawl_crawl'
|
||||
default:
|
||||
return 'firecrawl_scrape'
|
||||
}
|
||||
},
|
||||
params: (params) => {
|
||||
const { operation, limit, ...rest } = params
|
||||
|
||||
switch (operation) {
|
||||
case 'crawl':
|
||||
return {
|
||||
...rest,
|
||||
limit: limit ? Number.parseInt(limit) : undefined,
|
||||
}
|
||||
default:
|
||||
return rest
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
inputs: {
|
||||
apiKey: { type: 'string', required: true },
|
||||
operation: { type: 'string', required: true },
|
||||
url: { type: 'string', required: false },
|
||||
limit: { type: 'string', required: false },
|
||||
query: { type: 'string', required: false },
|
||||
scrapeOptions: { type: 'json', required: false },
|
||||
},
|
||||
@@ -95,5 +123,9 @@ export const FirecrawlBlock: BlockConfig<FirecrawlResponse> = {
|
||||
// Search output
|
||||
data: 'json',
|
||||
warning: 'any',
|
||||
// Crawl output
|
||||
pages: 'json',
|
||||
total: 'number',
|
||||
creditsUsed: 'number',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -19,9 +19,17 @@ export const NotionBlock: BlockConfig<NotionResponse> = {
|
||||
type: 'dropdown',
|
||||
layout: 'full',
|
||||
options: [
|
||||
// Read Operations
|
||||
{ label: 'Read Page', id: 'notion_read' },
|
||||
{ label: 'Append Content', id: 'notion_write' },
|
||||
{ label: 'Read Database', id: 'notion_read_database' },
|
||||
// Create Operations
|
||||
{ label: 'Create Page', id: 'notion_create_page' },
|
||||
{ label: 'Create Database', id: 'notion_create_database' },
|
||||
// Write Operations
|
||||
{ label: 'Append Content', id: 'notion_write' },
|
||||
// Query & Search Operations
|
||||
{ label: 'Query Database', id: 'notion_query_database' },
|
||||
{ label: 'Search Workspace', id: 'notion_search' },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -46,6 +54,17 @@ export const NotionBlock: BlockConfig<NotionResponse> = {
|
||||
value: 'notion_read',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'databaseId',
|
||||
title: 'Database ID',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Enter Notion database ID',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'notion_read_database',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'pageId',
|
||||
title: 'Page ID',
|
||||
@@ -58,23 +77,12 @@ export const NotionBlock: BlockConfig<NotionResponse> = {
|
||||
},
|
||||
},
|
||||
// Create operation fields
|
||||
{
|
||||
id: 'parentType',
|
||||
title: 'Parent Type',
|
||||
type: 'dropdown',
|
||||
layout: 'full',
|
||||
options: [
|
||||
{ label: 'Page', id: 'page' },
|
||||
{ label: 'Database', id: 'database' },
|
||||
],
|
||||
condition: { field: 'operation', value: 'notion_create_page' },
|
||||
},
|
||||
{
|
||||
id: 'parentId',
|
||||
title: 'Parent ID',
|
||||
title: 'Parent Page ID',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'ID of parent page or database',
|
||||
placeholder: 'ID of parent page',
|
||||
condition: { field: 'operation', value: 'notion_create_page' },
|
||||
},
|
||||
{
|
||||
@@ -83,18 +91,6 @@ export const NotionBlock: BlockConfig<NotionResponse> = {
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Title for the new page',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'notion_create_page',
|
||||
and: { field: 'parentType', value: 'page' },
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'properties',
|
||||
title: 'Page Properties (JSON)',
|
||||
type: 'long-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Enter page properties as JSON object',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'notion_create_page',
|
||||
@@ -123,28 +119,126 @@ export const NotionBlock: BlockConfig<NotionResponse> = {
|
||||
value: 'notion_create_page',
|
||||
},
|
||||
},
|
||||
// Query Database Fields
|
||||
{
|
||||
id: 'databaseId',
|
||||
title: 'Database ID',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Enter Notion database ID',
|
||||
condition: { field: 'operation', value: 'notion_query_database' },
|
||||
},
|
||||
{
|
||||
id: 'filter',
|
||||
title: 'Filter (JSON)',
|
||||
type: 'long-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Enter filter conditions as JSON (optional)',
|
||||
condition: { field: 'operation', value: 'notion_query_database' },
|
||||
},
|
||||
{
|
||||
id: 'sorts',
|
||||
title: 'Sort Criteria (JSON)',
|
||||
type: 'long-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Enter sort criteria as JSON array (optional)',
|
||||
condition: { field: 'operation', value: 'notion_query_database' },
|
||||
},
|
||||
{
|
||||
id: 'pageSize',
|
||||
title: 'Page Size',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Number of results (default: 100, max: 100)',
|
||||
condition: { field: 'operation', value: 'notion_query_database' },
|
||||
},
|
||||
// Search Fields
|
||||
{
|
||||
id: 'query',
|
||||
title: 'Search Query',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Enter search terms (leave empty for all pages)',
|
||||
condition: { field: 'operation', value: 'notion_search' },
|
||||
},
|
||||
{
|
||||
id: 'filterType',
|
||||
title: 'Filter Type',
|
||||
type: 'dropdown',
|
||||
layout: 'full',
|
||||
options: [
|
||||
{ label: 'All', id: 'all' },
|
||||
{ label: 'Pages Only', id: 'page' },
|
||||
{ label: 'Databases Only', id: 'database' },
|
||||
],
|
||||
condition: { field: 'operation', value: 'notion_search' },
|
||||
},
|
||||
// Create Database Fields
|
||||
{
|
||||
id: 'parentId',
|
||||
title: 'Parent Page ID',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'ID of parent page where database will be created',
|
||||
condition: { field: 'operation', value: 'notion_create_database' },
|
||||
},
|
||||
{
|
||||
id: 'title',
|
||||
title: 'Database Title',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Title for the new database',
|
||||
condition: { field: 'operation', value: 'notion_create_database' },
|
||||
},
|
||||
{
|
||||
id: 'properties',
|
||||
title: 'Database Properties (JSON)',
|
||||
type: 'long-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Enter database properties as JSON object',
|
||||
condition: { field: 'operation', value: 'notion_create_database' },
|
||||
},
|
||||
],
|
||||
tools: {
|
||||
access: ['notion_read', 'notion_write', 'notion_create_page'],
|
||||
access: [
|
||||
'notion_read',
|
||||
'notion_read_database',
|
||||
'notion_write',
|
||||
'notion_create_page',
|
||||
'notion_query_database',
|
||||
'notion_search',
|
||||
'notion_create_database',
|
||||
],
|
||||
config: {
|
||||
tool: (params) => {
|
||||
switch (params.operation) {
|
||||
case 'notion_read':
|
||||
return 'notion_read'
|
||||
case 'notion_read_database':
|
||||
return 'notion_read_database'
|
||||
case 'notion_write':
|
||||
return 'notion_write'
|
||||
case 'notion_create_page':
|
||||
return 'notion_create_page'
|
||||
case 'notion_query_database':
|
||||
return 'notion_query_database'
|
||||
case 'notion_search':
|
||||
return 'notion_search'
|
||||
case 'notion_create_database':
|
||||
return 'notion_create_database'
|
||||
default:
|
||||
return 'notion_read'
|
||||
}
|
||||
},
|
||||
params: (params) => {
|
||||
const { credential, operation, properties, ...rest } = params
|
||||
const { credential, operation, properties, filter, sorts, ...rest } = params
|
||||
|
||||
// Parse properties from JSON string for create operations
|
||||
let parsedProperties
|
||||
if (operation === 'notion_create_page' && properties) {
|
||||
if (
|
||||
(operation === 'notion_create_page' || operation === 'notion_create_database') &&
|
||||
properties
|
||||
) {
|
||||
try {
|
||||
parsedProperties = JSON.parse(properties)
|
||||
} catch (error) {
|
||||
@@ -154,10 +248,36 @@ export const NotionBlock: BlockConfig<NotionResponse> = {
|
||||
}
|
||||
}
|
||||
|
||||
// Parse filter for query database operations
|
||||
let parsedFilter
|
||||
if (operation === 'notion_query_database' && filter) {
|
||||
try {
|
||||
parsedFilter = JSON.parse(filter)
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Invalid JSON for filter: ${error instanceof Error ? error.message : String(error)}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Parse sorts for query database operations
|
||||
let parsedSorts
|
||||
if (operation === 'notion_query_database' && sorts) {
|
||||
try {
|
||||
parsedSorts = JSON.parse(sorts)
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Invalid JSON for sorts: ${error instanceof Error ? error.message : String(error)}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...rest,
|
||||
accessToken: credential,
|
||||
...(parsedProperties ? { properties: parsedProperties } : {}),
|
||||
...(parsedFilter ? { filter: JSON.stringify(parsedFilter) } : {}),
|
||||
...(parsedSorts ? { sorts: JSON.stringify(parsedSorts) } : {}),
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -168,10 +288,16 @@ export const NotionBlock: BlockConfig<NotionResponse> = {
|
||||
pageId: { type: 'string', required: false },
|
||||
content: { type: 'string', required: false },
|
||||
// Create page inputs
|
||||
parentType: { type: 'string', required: true },
|
||||
parentId: { type: 'string', required: true },
|
||||
parentId: { type: 'string', required: false },
|
||||
title: { type: 'string', required: false },
|
||||
properties: { type: 'string', required: false },
|
||||
// Query database inputs
|
||||
databaseId: { type: 'string', required: false },
|
||||
filter: { type: 'string', required: false },
|
||||
sorts: { type: 'string', required: false },
|
||||
pageSize: { type: 'number', required: false },
|
||||
// Search inputs
|
||||
query: { type: 'string', required: false },
|
||||
filterType: { type: 'string', required: false },
|
||||
},
|
||||
outputs: {
|
||||
content: 'string',
|
||||
|
||||
+116
-10
@@ -7,7 +7,7 @@ export const SlackBlock: BlockConfig<SlackResponse> = {
|
||||
name: 'Slack',
|
||||
description: 'Send messages to Slack',
|
||||
longDescription:
|
||||
"Comprehensive Slack integration with OAuth authentication. Send formatted messages using Slack's mrkdwn syntax or Block Kit.",
|
||||
"Comprehensive Slack integration with OAuth authentication. Send formatted messages using Slack's mrkdwn syntax.",
|
||||
docsLink: 'https://docs.simstudio.ai/tools/slack',
|
||||
category: 'tools',
|
||||
bgColor: '#611f69',
|
||||
@@ -18,7 +18,11 @@ export const SlackBlock: BlockConfig<SlackResponse> = {
|
||||
title: 'Operation',
|
||||
type: 'dropdown',
|
||||
layout: 'full',
|
||||
options: [{ label: 'Send Message', id: 'send' }],
|
||||
options: [
|
||||
{ label: 'Send Message', id: 'send' },
|
||||
{ label: 'Create Canvas', id: 'canvas' },
|
||||
{ label: 'Read Messages', id: 'read' },
|
||||
],
|
||||
value: () => 'send',
|
||||
},
|
||||
{
|
||||
@@ -41,13 +45,14 @@ export const SlackBlock: BlockConfig<SlackResponse> = {
|
||||
serviceId: 'slack',
|
||||
requiredScopes: [
|
||||
'channels:read',
|
||||
'channels:history',
|
||||
'groups:read',
|
||||
'groups:history',
|
||||
'chat:write',
|
||||
'chat:write.public',
|
||||
'users:read',
|
||||
'files:read',
|
||||
'links:read',
|
||||
'links:write',
|
||||
'files:write',
|
||||
'canvases:write',
|
||||
],
|
||||
placeholder: 'Select Slack workspace',
|
||||
condition: {
|
||||
@@ -91,22 +96,87 @@ export const SlackBlock: BlockConfig<SlackResponse> = {
|
||||
type: 'long-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Enter your message (supports Slack mrkdwn)',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'send',
|
||||
},
|
||||
},
|
||||
// Canvas specific fields
|
||||
{
|
||||
id: 'title',
|
||||
title: 'Canvas Title',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Enter canvas title',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'canvas',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'content',
|
||||
title: 'Canvas Content',
|
||||
type: 'long-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Enter canvas content (markdown supported)',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'canvas',
|
||||
},
|
||||
},
|
||||
// Message Reader specific fields
|
||||
{
|
||||
id: 'limit',
|
||||
title: 'Message Limit',
|
||||
type: 'short-input',
|
||||
layout: 'half',
|
||||
placeholder: '50',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'read',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'oldest',
|
||||
title: 'Oldest Timestamp',
|
||||
type: 'short-input',
|
||||
layout: 'half',
|
||||
placeholder: 'ISO 8601 timestamp',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'read',
|
||||
},
|
||||
},
|
||||
],
|
||||
tools: {
|
||||
access: ['slack_message'],
|
||||
access: ['slack_message', 'slack_canvas', 'slack_message_reader'],
|
||||
config: {
|
||||
tool: (params) => {
|
||||
switch (params.operation) {
|
||||
case 'send':
|
||||
return 'slack_message'
|
||||
case 'canvas':
|
||||
return 'slack_canvas'
|
||||
case 'read':
|
||||
return 'slack_message_reader'
|
||||
default:
|
||||
throw new Error(`Invalid Slack operation: ${params.operation}`)
|
||||
}
|
||||
},
|
||||
params: (params) => {
|
||||
const { credential, authMethod, botToken, operation, channel, manualChannel, ...rest } =
|
||||
params
|
||||
const {
|
||||
credential,
|
||||
authMethod,
|
||||
botToken,
|
||||
operation,
|
||||
channel,
|
||||
manualChannel,
|
||||
title,
|
||||
content,
|
||||
limit,
|
||||
oldest,
|
||||
...rest
|
||||
} = params
|
||||
|
||||
// Handle channel input (selector or manual)
|
||||
const effectiveChannel = (channel || manualChannel || '').trim()
|
||||
@@ -118,7 +188,6 @@ export const SlackBlock: BlockConfig<SlackResponse> = {
|
||||
}
|
||||
|
||||
const baseParams: Record<string, any> = {
|
||||
...rest,
|
||||
channel: effectiveChannel,
|
||||
}
|
||||
|
||||
@@ -136,6 +205,36 @@ export const SlackBlock: BlockConfig<SlackResponse> = {
|
||||
baseParams.credential = credential
|
||||
}
|
||||
|
||||
// Handle operation-specific params
|
||||
switch (operation) {
|
||||
case 'send':
|
||||
if (!rest.text) {
|
||||
throw new Error('Message text is required for send operation')
|
||||
}
|
||||
baseParams.text = rest.text
|
||||
break
|
||||
|
||||
case 'canvas':
|
||||
if (!title || !content) {
|
||||
throw new Error('Title and content are required for canvas operation')
|
||||
}
|
||||
baseParams.title = title
|
||||
baseParams.content = content
|
||||
break
|
||||
|
||||
case 'read':
|
||||
if (limit) {
|
||||
const parsedLimit = Number.parseInt(limit, 10)
|
||||
baseParams.limit = !Number.isNaN(parsedLimit) ? parsedLimit : 10
|
||||
} else {
|
||||
baseParams.limit = 10
|
||||
}
|
||||
if (oldest) {
|
||||
baseParams.oldest = oldest
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
return baseParams
|
||||
},
|
||||
},
|
||||
@@ -147,10 +246,17 @@ export const SlackBlock: BlockConfig<SlackResponse> = {
|
||||
botToken: { type: 'string', required: false },
|
||||
channel: { type: 'string', required: false },
|
||||
manualChannel: { type: 'string', required: false },
|
||||
text: { type: 'string', required: true },
|
||||
text: { type: 'string', required: false },
|
||||
title: { type: 'string', required: false },
|
||||
content: { type: 'string', required: false },
|
||||
limit: { type: 'string', required: false },
|
||||
oldest: { type: 'string', required: false },
|
||||
},
|
||||
outputs: {
|
||||
ts: 'string',
|
||||
channel: 'string',
|
||||
canvas_id: 'string',
|
||||
title: 'string',
|
||||
messages: 'json',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { SupabaseIcon } from '@/components/icons'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import type { BlockConfig } from '@/blocks/types'
|
||||
import type { SupabaseResponse } from '@/tools/supabase/types'
|
||||
|
||||
const logger = createLogger('SupabaseBlock')
|
||||
|
||||
export const SupabaseBlock: BlockConfig<SupabaseResponse> = {
|
||||
type: 'supabase',
|
||||
name: 'Supabase',
|
||||
@@ -19,8 +22,11 @@ export const SupabaseBlock: BlockConfig<SupabaseResponse> = {
|
||||
type: 'dropdown',
|
||||
layout: 'full',
|
||||
options: [
|
||||
{ label: 'Read All Rows', id: 'query' },
|
||||
{ label: 'Insert Rows', id: 'insert' },
|
||||
{ label: 'Get Many Rows', id: 'query' },
|
||||
{ label: 'Get a Row', id: 'get_row' },
|
||||
{ label: 'Create a Row', id: 'insert' },
|
||||
{ label: 'Update a Row', id: 'update' },
|
||||
{ label: 'Delete a Row', id: 'delete' },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -28,6 +34,7 @@ export const SupabaseBlock: BlockConfig<SupabaseResponse> = {
|
||||
title: 'Project ID',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
password: true,
|
||||
placeholder: 'Your Supabase project ID (e.g., jdrkgepadsdopsntdlom)',
|
||||
},
|
||||
{
|
||||
@@ -39,12 +46,13 @@ export const SupabaseBlock: BlockConfig<SupabaseResponse> = {
|
||||
},
|
||||
{
|
||||
id: 'apiKey',
|
||||
title: 'Client Anon Key',
|
||||
title: 'Service Role Secret',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Your Supabase client anon key',
|
||||
placeholder: 'Your Supabase service role secret key',
|
||||
password: true,
|
||||
},
|
||||
// Data input for create/update operations
|
||||
{
|
||||
id: 'data',
|
||||
title: 'Data',
|
||||
@@ -53,9 +61,75 @@ export const SupabaseBlock: BlockConfig<SupabaseResponse> = {
|
||||
placeholder: '{\n "column1": "value1",\n "column2": "value2"\n}',
|
||||
condition: { field: 'operation', value: 'insert' },
|
||||
},
|
||||
{
|
||||
id: 'data',
|
||||
title: 'Data',
|
||||
type: 'code',
|
||||
layout: 'full',
|
||||
placeholder: '{\n "column1": "value1",\n "column2": "value2"\n}',
|
||||
condition: { field: 'operation', value: 'update' },
|
||||
},
|
||||
// Filter for get_row, update, delete operations (required)
|
||||
{
|
||||
id: 'filter',
|
||||
title: 'Filter (PostgREST syntax)',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'id=eq.123',
|
||||
condition: { field: 'operation', value: 'get_row' },
|
||||
},
|
||||
{
|
||||
id: 'filter',
|
||||
title: 'Filter (PostgREST syntax)',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'id=eq.123',
|
||||
condition: { field: 'operation', value: 'update' },
|
||||
},
|
||||
{
|
||||
id: 'filter',
|
||||
title: 'Filter (PostgREST syntax)',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'id=eq.123',
|
||||
condition: { field: 'operation', value: 'delete' },
|
||||
},
|
||||
// Optional filter for query operation
|
||||
{
|
||||
id: 'filter',
|
||||
title: 'Filter (PostgREST syntax)',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'status=eq.active',
|
||||
condition: { field: 'operation', value: 'query' },
|
||||
},
|
||||
// Optional order by for query operation
|
||||
{
|
||||
id: 'orderBy',
|
||||
title: 'Order By',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'column_name (add DESC for descending)',
|
||||
condition: { field: 'operation', value: 'query' },
|
||||
},
|
||||
// Optional limit for query operation
|
||||
{
|
||||
id: 'limit',
|
||||
title: 'Limit',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: '100',
|
||||
condition: { field: 'operation', value: 'query' },
|
||||
},
|
||||
],
|
||||
tools: {
|
||||
access: ['supabase_query', 'supabase_insert'],
|
||||
access: [
|
||||
'supabase_query',
|
||||
'supabase_insert',
|
||||
'supabase_get_row',
|
||||
'supabase_update',
|
||||
'supabase_delete',
|
||||
],
|
||||
config: {
|
||||
tool: (params) => {
|
||||
switch (params.operation) {
|
||||
@@ -63,29 +137,49 @@ export const SupabaseBlock: BlockConfig<SupabaseResponse> = {
|
||||
return 'supabase_query'
|
||||
case 'insert':
|
||||
return 'supabase_insert'
|
||||
case 'get_row':
|
||||
return 'supabase_get_row'
|
||||
case 'update':
|
||||
return 'supabase_update'
|
||||
case 'delete':
|
||||
return 'supabase_delete'
|
||||
default:
|
||||
throw new Error(`Invalid Supabase operation: ${params.operation}`)
|
||||
}
|
||||
},
|
||||
params: (params) => {
|
||||
const { data, ...rest } = params
|
||||
const { operation, data, filter, ...rest } = params
|
||||
|
||||
// Parse JSON data if it's a string
|
||||
let parsedData
|
||||
if (data && typeof data === 'string') {
|
||||
if (data && typeof data === 'string' && data.trim()) {
|
||||
try {
|
||||
parsedData = JSON.parse(data)
|
||||
} catch (_e) {
|
||||
throw new Error('Invalid JSON data format')
|
||||
}
|
||||
} else {
|
||||
} else if (data && typeof data === 'object') {
|
||||
parsedData = data
|
||||
}
|
||||
|
||||
return {
|
||||
...rest,
|
||||
data: parsedData,
|
||||
// Handle filter - just pass through PostgREST syntax
|
||||
let parsedFilter
|
||||
if (filter && typeof filter === 'string' && filter.trim()) {
|
||||
parsedFilter = filter.trim()
|
||||
}
|
||||
|
||||
// Build params object, only including defined values
|
||||
const result = { ...rest }
|
||||
|
||||
if (parsedData !== undefined) {
|
||||
result.data = parsedData
|
||||
}
|
||||
|
||||
if (parsedFilter !== undefined && parsedFilter !== '') {
|
||||
result.filter = parsedFilter
|
||||
}
|
||||
|
||||
return result
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -94,8 +188,13 @@ export const SupabaseBlock: BlockConfig<SupabaseResponse> = {
|
||||
projectId: { type: 'string', required: true },
|
||||
table: { type: 'string', required: true },
|
||||
apiKey: { type: 'string', required: true },
|
||||
// Insert operation inputs
|
||||
data: { type: 'string', required: false },
|
||||
// Data for insert/update operations
|
||||
data: { type: 'json', required: false },
|
||||
// Filter for operations
|
||||
filter: { type: 'string', required: false },
|
||||
// Query operation inputs
|
||||
orderBy: { type: 'string', required: false },
|
||||
limit: { type: 'number', required: false },
|
||||
},
|
||||
outputs: {
|
||||
message: 'string',
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Blocks Registry
|
||||
*
|
||||
*/
|
||||
// Import all blocks directly here
|
||||
|
||||
import { AgentBlock } from '@/blocks/blocks/agent'
|
||||
import { AirtableBlock } from '@/blocks/blocks/airtable'
|
||||
import { ApiBlock } from '@/blocks/blocks/api'
|
||||
@@ -133,7 +133,6 @@ export const registry: Record<string, BlockConfig> = {
|
||||
youtube: YouTubeBlock,
|
||||
}
|
||||
|
||||
// Helper functions to access the registry
|
||||
export const getBlock = (type: string): BlockConfig | undefined => registry[type]
|
||||
|
||||
export const getBlocksByCategory = (category: 'blocks' | 'tools' | 'triggers'): BlockConfig[] =>
|
||||
|
||||
@@ -993,13 +993,14 @@ export const auth = betterAuth({
|
||||
scopes: [
|
||||
// Bot token scopes only - app acts as a bot user
|
||||
'channels:read',
|
||||
'channels:history',
|
||||
'groups:read',
|
||||
'groups:history',
|
||||
'chat:write',
|
||||
'chat:write.public',
|
||||
'files:read',
|
||||
'links:read',
|
||||
'links:write',
|
||||
'users:read',
|
||||
'files:write',
|
||||
'canvases:write',
|
||||
],
|
||||
responseType: 'code',
|
||||
accessType: 'offline',
|
||||
|
||||
@@ -140,7 +140,7 @@ const nextConfig: NextConfig = {
|
||||
},
|
||||
{
|
||||
key: 'Content-Security-Policy',
|
||||
value: `default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.google.com https://apis.google.com https://*.vercel-scripts.com https://*.vercel-insights.com https://vercel.live https://*.vercel.live https://vercel.com https://*.vercel.app https://vitals.vercel-insights.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: blob: https://*.googleusercontent.com https://*.google.com https://*.atlassian.com https://cdn.discordapp.com https://*.githubusercontent.com; media-src 'self' blob:; font-src 'self' https://fonts.gstatic.com; connect-src 'self' ${env.NEXT_PUBLIC_APP_URL || ''} ${env.OLLAMA_URL || 'http://localhost:11434'} ${env.NEXT_PUBLIC_SOCKET_URL || 'http://localhost:3002'} ${env.NEXT_PUBLIC_SOCKET_URL?.replace('http://', 'ws://').replace('https://', 'wss://') || 'ws://localhost:3002'} https://*.up.railway.app wss://*.up.railway.app https://api.browser-use.com https://*.googleapis.com https://*.amazonaws.com https://*.s3.amazonaws.com https://*.blob.core.windows.net https://*.vercel-insights.com https://vitals.vercel-insights.com https://*.atlassian.com https://vercel.live https://*.vercel.live https://vercel.com https://*.vercel.app wss://*.vercel.app; frame-src https://drive.google.com https://*.google.com; frame-ancestors 'self'; form-action 'self'; base-uri 'self'; object-src 'none'`,
|
||||
value: `default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.google.com https://apis.google.com https://*.vercel-scripts.com https://*.vercel-insights.com https://vercel.live https://*.vercel.live https://vercel.com https://*.vercel.app https://vitals.vercel-insights.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: blob: https://*.googleusercontent.com https://*.google.com https://*.atlassian.com https://cdn.discordapp.com https://*.githubusercontent.com; media-src 'self' blob:; font-src 'self' https://fonts.gstatic.com; connect-src 'self' ${env.NEXT_PUBLIC_APP_URL || ''} ${env.OLLAMA_URL || 'http://localhost:11434'} ${env.NEXT_PUBLIC_SOCKET_URL || 'http://localhost:3002'} ${env.NEXT_PUBLIC_SOCKET_URL?.replace('http://', 'ws://').replace('https://', 'wss://') || 'ws://localhost:3002'} https://*.up.railway.app wss://*.up.railway.app https://api.browser-use.com https://api.exa.ai https://api.firecrawl.dev https://*.googleapis.com https://*.amazonaws.com https://*.s3.amazonaws.com https://*.blob.core.windows.net https://*.vercel-insights.com https://vitals.vercel-insights.com https://*.atlassian.com https://*.supabase.co https://vercel.live https://*.vercel.live https://vercel.com https://*.vercel.app wss://*.vercel.app; frame-src https://drive.google.com https://*.google.com; frame-ancestors 'self'; form-action 'self'; base-uri 'self'; object-src 'none'`,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { AirtableCreateParams, AirtableCreateResponse } from './types'
|
||||
import type { AirtableCreateParams, AirtableCreateResponse } from '@/tools/airtable/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const airtableCreateRecordsTool: ToolConfig<AirtableCreateParams, AirtableCreateResponse> = {
|
||||
id: 'airtable_create_records',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { AirtableGetParams, AirtableGetResponse } from './types'
|
||||
import type { AirtableGetParams, AirtableGetResponse } from '@/tools/airtable/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
// import { logger } from '@/utils/logger' // Removed logger due to import issues
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { airtableCreateRecordsTool } from './create_records'
|
||||
import { airtableGetRecordTool } from './get_record'
|
||||
import { airtableListRecordsTool } from './list_records'
|
||||
import { airtableUpdateMultipleRecordsTool } from './update_multiple_records'
|
||||
import { airtableUpdateRecordTool } from './update_record'
|
||||
import { airtableCreateRecordsTool } from '@/tools/airtable/create_records'
|
||||
import { airtableGetRecordTool } from '@/tools/airtable/get_record'
|
||||
import { airtableListRecordsTool } from '@/tools/airtable/list_records'
|
||||
import { airtableUpdateMultipleRecordsTool } from '@/tools/airtable/update_multiple_records'
|
||||
import { airtableUpdateRecordTool } from '@/tools/airtable/update_record'
|
||||
|
||||
export {
|
||||
airtableCreateRecordsTool,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { AirtableListParams, AirtableListResponse } from './types'
|
||||
import type { AirtableListParams, AirtableListResponse } from '@/tools/airtable/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const airtableListRecordsTool: ToolConfig<AirtableListParams, AirtableListResponse> = {
|
||||
id: 'airtable_list_records',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ToolResponse } from '../types'
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
// Common types
|
||||
export interface AirtableRecord {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { AirtableUpdateMultipleParams, AirtableUpdateMultipleResponse } from './types'
|
||||
import type {
|
||||
AirtableUpdateMultipleParams,
|
||||
AirtableUpdateMultipleResponse,
|
||||
} from '@/tools/airtable/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
// import { logger } from '@/utils/logger' // Removed logger due to import issues
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { AirtableUpdateParams, AirtableUpdateResponse } from './types'
|
||||
import type { AirtableUpdateParams, AirtableUpdateResponse } from '@/tools/airtable/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
// import { logger } from '@/utils/logger' // Removed logger due to import issues
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import { runTaskTool } from './run_task'
|
||||
import { runTaskTool } from '@/tools/browser_use/run_task'
|
||||
|
||||
export const browserUseRunTaskTool = runTaskTool
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { BrowserUseRunTaskParams, BrowserUseRunTaskResponse } from './types'
|
||||
import type { BrowserUseRunTaskParams, BrowserUseRunTaskResponse } from '@/tools/browser_use/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('BrowserUseTool')
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ToolResponse } from '../types'
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
export interface BrowserUseRunTaskParams {
|
||||
task: string
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import { clayPopulateTool } from './populate'
|
||||
import { clayPopulateTool } from '@/tools/clay/populate'
|
||||
|
||||
export { clayPopulateTool }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { ClayPopulateParams, ClayPopulateResponse } from './types'
|
||||
import type { ClayPopulateParams, ClayPopulateResponse } from '@/tools/clay/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const clayPopulateTool: ToolConfig<ClayPopulateParams, ClayPopulateResponse> = {
|
||||
id: 'clay_populate',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ToolResponse } from '../types'
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
export interface ClayPopulateParams {
|
||||
webhookURL: string
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { confluenceRetrieveTool } from './retrieve'
|
||||
import { confluenceUpdateTool } from './update'
|
||||
import { confluenceRetrieveTool } from '@/tools/confluence/retrieve'
|
||||
import { confluenceUpdateTool } from '@/tools/confluence/update'
|
||||
|
||||
export { confluenceRetrieveTool }
|
||||
export { confluenceUpdateTool }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { ConfluenceRetrieveParams, ConfluenceRetrieveResponse } from './types'
|
||||
import type { ConfluenceRetrieveParams, ConfluenceRetrieveResponse } from '@/tools/confluence/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const confluenceRetrieveTool: ToolConfig<
|
||||
ConfluenceRetrieveParams,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ToolResponse } from '../types'
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
export interface ConfluenceRetrieveParams {
|
||||
accessToken: string
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { ConfluenceUpdateParams, ConfluenceUpdateResponse } from './types'
|
||||
import type { ConfluenceUpdateParams, ConfluenceUpdateResponse } from '@/tools/confluence/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const confluenceUpdateTool: ToolConfig<ConfluenceUpdateParams, ConfluenceUpdateResponse> = {
|
||||
id: 'confluence_update',
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import type { ToolConfig } from '../types'
|
||||
import type {
|
||||
DiscordAPIError,
|
||||
DiscordGetMessagesParams,
|
||||
DiscordGetMessagesResponse,
|
||||
DiscordMessage,
|
||||
} from './types'
|
||||
} from '@/tools/discord/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('DiscordGetMessages')
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import type { ToolConfig } from '../types'
|
||||
import type {
|
||||
DiscordAPIError,
|
||||
DiscordGetServerParams,
|
||||
DiscordGetServerResponse,
|
||||
DiscordGuild,
|
||||
} from './types'
|
||||
} from '@/tools/discord/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('DiscordGetServer')
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import type { ToolConfig } from '../types'
|
||||
import type {
|
||||
DiscordAPIError,
|
||||
DiscordGetUserParams,
|
||||
DiscordGetUserResponse,
|
||||
DiscordUser,
|
||||
} from './types'
|
||||
} from '@/tools/discord/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('DiscordGetUser')
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { discordGetMessagesTool } from './get_messages'
|
||||
import { discordGetServerTool } from './get_server'
|
||||
import { discordGetUserTool } from './get_user'
|
||||
import { discordSendMessageTool } from './send_message'
|
||||
import { discordGetMessagesTool } from '@/tools/discord/get_messages'
|
||||
import { discordGetServerTool } from '@/tools/discord/get_server'
|
||||
import { discordGetUserTool } from '@/tools/discord/get_user'
|
||||
import { discordSendMessageTool } from '@/tools/discord/send_message'
|
||||
|
||||
export { discordSendMessageTool, discordGetMessagesTool, discordGetServerTool, discordGetUserTool }
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import type { ToolConfig } from '../types'
|
||||
import type {
|
||||
DiscordAPIError,
|
||||
DiscordMessage,
|
||||
DiscordSendMessageParams,
|
||||
DiscordSendMessageResponse,
|
||||
} from './types'
|
||||
} from '@/tools/discord/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('DiscordSendMessage')
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ToolConfig, ToolResponse } from '../types'
|
||||
import type { ToolConfig, ToolResponse } from '@/tools/types'
|
||||
|
||||
interface DocsSearchParams {
|
||||
query: string
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import { elevenLabsTtsTool } from './tts'
|
||||
import { elevenLabsTtsTool } from '@/tools/elevenlabs/tts'
|
||||
|
||||
export { elevenLabsTtsTool }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { ExaAnswerParams, ExaAnswerResponse } from './types'
|
||||
import type { ExaAnswerParams, ExaAnswerResponse } from '@/tools/exa/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const answerTool: ToolConfig<ExaAnswerParams, ExaAnswerResponse> = {
|
||||
id: 'exa_answer',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { ExaFindSimilarLinksParams, ExaFindSimilarLinksResponse } from './types'
|
||||
import type { ExaFindSimilarLinksParams, ExaFindSimilarLinksResponse } from '@/tools/exa/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const findSimilarLinksTool: ToolConfig<
|
||||
ExaFindSimilarLinksParams,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { ExaGetContentsParams, ExaGetContentsResponse } from './types'
|
||||
import type { ExaGetContentsParams, ExaGetContentsResponse } from '@/tools/exa/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const getContentsTool: ToolConfig<ExaGetContentsParams, ExaGetContentsResponse> = {
|
||||
id: 'exa_get_contents',
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { answerTool } from './answer'
|
||||
import { findSimilarLinksTool } from './find_similar_links'
|
||||
import { getContentsTool } from './get_contents'
|
||||
import { searchTool } from './search'
|
||||
import { answerTool } from '@/tools/exa/answer'
|
||||
import { findSimilarLinksTool } from '@/tools/exa/find_similar_links'
|
||||
import { getContentsTool } from '@/tools/exa/get_contents'
|
||||
import { researchTool } from '@/tools/exa/research'
|
||||
import { searchTool } from '@/tools/exa/search'
|
||||
|
||||
export const exaAnswerTool = answerTool
|
||||
export const exaFindSimilarLinksTool = findSimilarLinksTool
|
||||
export const exaGetContentsTool = getContentsTool
|
||||
export const exaSearchTool = searchTool
|
||||
export const exaResearchTool = researchTool
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import type { ExaResearchParams, ExaResearchResponse } from '@/tools/exa/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('ExaResearchTool')
|
||||
|
||||
const POLL_INTERVAL_MS = 5000 // 5 seconds between polls
|
||||
const MAX_POLL_TIME_MS = 300000 // 5 minutes maximum polling time
|
||||
|
||||
export const researchTool: ToolConfig<ExaResearchParams, ExaResearchResponse> = {
|
||||
id: 'exa_research',
|
||||
name: 'Exa Research',
|
||||
description:
|
||||
'Perform comprehensive research using AI to generate detailed reports with citations',
|
||||
version: '1.0.0',
|
||||
params: {
|
||||
query: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Research query or topic',
|
||||
},
|
||||
includeText: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Include full text content in results',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Exa AI API Key',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: 'https://api.exa.ai/research/v0/tasks',
|
||||
method: 'POST',
|
||||
isInternalRoute: false,
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': params.apiKey,
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: any = {
|
||||
instructions: params.query,
|
||||
model: 'exa-research',
|
||||
output: {
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
results: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
title: { type: 'string' },
|
||||
url: { type: 'string' },
|
||||
summary: { type: 'string' },
|
||||
text: { type: 'string' },
|
||||
publishedDate: { type: 'string' },
|
||||
author: { type: 'string' },
|
||||
score: { type: 'number' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
required: ['results'],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return body
|
||||
},
|
||||
},
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.message || data.error || 'Failed to create research task')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
taskId: data.id,
|
||||
research: [],
|
||||
},
|
||||
}
|
||||
},
|
||||
postProcess: async (result, params) => {
|
||||
if (!result.success) {
|
||||
return result
|
||||
}
|
||||
|
||||
const taskId = result.output.taskId
|
||||
logger.info(`Exa research task ${taskId} created, polling for completion...`)
|
||||
|
||||
let elapsedTime = 0
|
||||
|
||||
while (elapsedTime < MAX_POLL_TIME_MS) {
|
||||
try {
|
||||
const statusResponse = await fetch(`https://api.exa.ai/research/v0/tasks/${taskId}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'x-api-key': params.apiKey,
|
||||
},
|
||||
})
|
||||
|
||||
if (!statusResponse.ok) {
|
||||
throw new Error(`Failed to get task status: ${statusResponse.statusText}`)
|
||||
}
|
||||
|
||||
const taskData = await statusResponse.json()
|
||||
logger.info(`Exa research task ${taskId} status: ${taskData.status}`)
|
||||
|
||||
if (taskData.status === 'completed') {
|
||||
result.output = {
|
||||
research: taskData.data?.results || [
|
||||
{
|
||||
title: 'Research Complete',
|
||||
url: '',
|
||||
summary: taskData.data || 'Research completed successfully',
|
||||
text: undefined,
|
||||
publishedDate: undefined,
|
||||
author: undefined,
|
||||
score: 1.0,
|
||||
},
|
||||
],
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
if (taskData.status === 'failed') {
|
||||
return {
|
||||
...result,
|
||||
success: false,
|
||||
error: `Research task failed: ${taskData.error || 'Unknown error'}`,
|
||||
}
|
||||
}
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS))
|
||||
elapsedTime += POLL_INTERVAL_MS
|
||||
} catch (error: any) {
|
||||
logger.error('Error polling for research task status:', {
|
||||
message: error.message || 'Unknown error',
|
||||
taskId,
|
||||
})
|
||||
|
||||
return {
|
||||
...result,
|
||||
success: false,
|
||||
error: `Error polling for research task status: ${error.message || 'Unknown error'}`,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.warn(
|
||||
`Research task ${taskId} did not complete within the maximum polling time (${MAX_POLL_TIME_MS / 1000}s)`
|
||||
)
|
||||
return {
|
||||
...result,
|
||||
success: false,
|
||||
error: `Research task did not complete within the maximum polling time (${MAX_POLL_TIME_MS / 1000}s)`,
|
||||
}
|
||||
},
|
||||
transformError: (error) => {
|
||||
const errorMessage = error?.message || ''
|
||||
if (errorMessage.includes('401')) {
|
||||
return new Error('Invalid API key. Please check your Exa AI API key.')
|
||||
}
|
||||
if (errorMessage.includes('429')) {
|
||||
return new Error('Rate limit exceeded. Please try again later.')
|
||||
}
|
||||
return error
|
||||
},
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { ExaSearchParams, ExaSearchResponse } from './types'
|
||||
import type { ExaSearchParams, ExaSearchResponse } from '@/tools/exa/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const searchTool: ToolConfig<ExaSearchParams, ExaSearchResponse> = {
|
||||
id: 'exa_search',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Common types for Exa AI tools
|
||||
import type { ToolResponse } from '../types'
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
// Common parameters for all Exa AI tools
|
||||
export interface ExaBaseParams {
|
||||
@@ -89,8 +89,30 @@ export interface ExaAnswerResponse extends ToolResponse {
|
||||
}
|
||||
}
|
||||
|
||||
// Research tool types
|
||||
export interface ExaResearchParams extends ExaBaseParams {
|
||||
query: string
|
||||
includeText?: boolean
|
||||
}
|
||||
|
||||
export interface ExaResearchResponse extends ToolResponse {
|
||||
output: {
|
||||
taskId?: string
|
||||
research: {
|
||||
title: string
|
||||
url: string
|
||||
summary: string
|
||||
text?: string
|
||||
publishedDate?: string
|
||||
author?: string
|
||||
score: number
|
||||
}[]
|
||||
}
|
||||
}
|
||||
|
||||
export type ExaResponse =
|
||||
| ExaSearchResponse
|
||||
| ExaGetContentsResponse
|
||||
| ExaFindSimilarLinksResponse
|
||||
| ExaAnswerResponse
|
||||
| ExaResearchResponse
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import { fileParserTool } from './parser'
|
||||
import { fileParserTool } from '@/tools/file/parser'
|
||||
|
||||
export const fileParseTool = fileParserTool
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import type { ToolConfig } from '../types'
|
||||
import type {
|
||||
FileParseResult,
|
||||
FileParserInput,
|
||||
FileParserOutput,
|
||||
FileParserOutputData,
|
||||
} from './types'
|
||||
} from '@/tools/file/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('FileParserTool')
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ToolResponse } from '../types'
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
export interface FileParserInput {
|
||||
filePath: string | string[]
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import type { FirecrawlCrawlParams, FirecrawlCrawlResponse } from '@/tools/firecrawl/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('FirecrawlCrawlTool')
|
||||
|
||||
const POLL_INTERVAL_MS = 5000 // 5 seconds between polls
|
||||
const MAX_POLL_TIME_MS = 300000 // 5 minutes maximum polling time
|
||||
|
||||
export const crawlTool: ToolConfig<FirecrawlCrawlParams, FirecrawlCrawlResponse> = {
|
||||
id: 'firecrawl_crawl',
|
||||
name: 'Firecrawl Crawl',
|
||||
description: 'Crawl entire websites and extract structured content from all accessible pages',
|
||||
version: '1.0.0',
|
||||
params: {
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The website URL to crawl',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Maximum number of pages to crawl (default: 100)',
|
||||
},
|
||||
onlyMainContent: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Extract only main content from pages',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Firecrawl API Key',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: 'https://api.firecrawl.dev/v1/crawl',
|
||||
method: 'POST',
|
||||
isInternalRoute: false,
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
}),
|
||||
body: (params) => ({
|
||||
url: params.url,
|
||||
limit: Number(params.limit) || 100,
|
||||
scrapeOptions: {
|
||||
formats: ['markdown'],
|
||||
onlyMainContent: params.onlyMainContent || false,
|
||||
},
|
||||
}),
|
||||
},
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || data.message || 'Failed to create crawl job')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
jobId: data.jobId || data.id,
|
||||
pages: [],
|
||||
total: 0,
|
||||
creditsUsed: 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
postProcess: async (result, params) => {
|
||||
if (!result.success) {
|
||||
return result
|
||||
}
|
||||
|
||||
const jobId = result.output.jobId
|
||||
logger.info(`Firecrawl crawl job ${jobId} created, polling for completion...`)
|
||||
|
||||
let elapsedTime = 0
|
||||
|
||||
while (elapsedTime < MAX_POLL_TIME_MS) {
|
||||
try {
|
||||
const statusResponse = await fetch(`/api/tools/firecrawl/crawl/${jobId}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
},
|
||||
})
|
||||
|
||||
if (!statusResponse.ok) {
|
||||
throw new Error(`Failed to get crawl status: ${statusResponse.statusText}`)
|
||||
}
|
||||
|
||||
const crawlData = await statusResponse.json()
|
||||
logger.info(`Firecrawl crawl job ${jobId} status: ${crawlData.status}`)
|
||||
|
||||
if (crawlData.status === 'completed') {
|
||||
result.output = {
|
||||
pages: crawlData.data || [],
|
||||
total: crawlData.total || 0,
|
||||
creditsUsed: crawlData.creditsUsed || 0,
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
if (crawlData.status === 'failed') {
|
||||
return {
|
||||
...result,
|
||||
success: false,
|
||||
error: `Crawl job failed: ${crawlData.error || 'Unknown error'}`,
|
||||
}
|
||||
}
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS))
|
||||
elapsedTime += POLL_INTERVAL_MS
|
||||
} catch (error: any) {
|
||||
logger.error('Error polling for crawl job status:', {
|
||||
message: error.message || 'Unknown error',
|
||||
jobId,
|
||||
})
|
||||
|
||||
return {
|
||||
...result,
|
||||
success: false,
|
||||
error: `Error polling for crawl job status: ${error.message || 'Unknown error'}`,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.warn(
|
||||
`Crawl job ${jobId} did not complete within the maximum polling time (${MAX_POLL_TIME_MS / 1000}s)`
|
||||
)
|
||||
return {
|
||||
...result,
|
||||
success: false,
|
||||
error: `Crawl job did not complete within the maximum polling time (${MAX_POLL_TIME_MS / 1000}s)`,
|
||||
}
|
||||
},
|
||||
transformError: (error) => {
|
||||
const errorMessage = error?.message || ''
|
||||
if (errorMessage.includes('401')) {
|
||||
return new Error('Invalid API key. Please check your Firecrawl API key.')
|
||||
}
|
||||
if (errorMessage.includes('429')) {
|
||||
return new Error('Rate limit exceeded. Please try again later.')
|
||||
}
|
||||
if (errorMessage.includes('402')) {
|
||||
return new Error('Insufficient credits. Please check your Firecrawl account.')
|
||||
}
|
||||
return error
|
||||
},
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { scrapeTool } from './scrape'
|
||||
import { searchTool } from './search'
|
||||
import { crawlTool } from '@/tools/firecrawl/crawl'
|
||||
import { scrapeTool } from '@/tools/firecrawl/scrape'
|
||||
import { searchTool } from '@/tools/firecrawl/search'
|
||||
|
||||
export { scrapeTool, searchTool }
|
||||
export { scrapeTool, searchTool, crawlTool }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { ScrapeParams, ScrapeResponse } from './types'
|
||||
import type { ScrapeParams, ScrapeResponse } from '@/tools/firecrawl/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const scrapeTool: ToolConfig<ScrapeParams, ScrapeResponse> = {
|
||||
id: 'firecrawl_scrape',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { SearchParams, SearchResponse } from './types'
|
||||
import type { SearchParams, SearchResponse } from '@/tools/firecrawl/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const searchTool: ToolConfig<SearchParams, SearchResponse> = {
|
||||
id: 'firecrawl_search',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ToolResponse } from '../types'
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
export interface ScrapeParams {
|
||||
apiKey: string
|
||||
@@ -14,6 +14,13 @@ export interface SearchParams {
|
||||
query: string
|
||||
}
|
||||
|
||||
export interface FirecrawlCrawlParams {
|
||||
apiKey: string
|
||||
url: string
|
||||
limit?: number
|
||||
onlyMainContent?: boolean
|
||||
}
|
||||
|
||||
export interface ScrapeResponse extends ToolResponse {
|
||||
output: {
|
||||
markdown: string
|
||||
@@ -59,4 +66,23 @@ export interface SearchResponse extends ToolResponse {
|
||||
}
|
||||
}
|
||||
|
||||
export type FirecrawlResponse = ScrapeResponse | SearchResponse
|
||||
export interface FirecrawlCrawlResponse extends ToolResponse {
|
||||
output: {
|
||||
jobId?: string
|
||||
pages: Array<{
|
||||
markdown: string
|
||||
html?: string
|
||||
metadata: {
|
||||
title: string
|
||||
description: string
|
||||
language: string
|
||||
sourceURL: string
|
||||
statusCode: number
|
||||
}
|
||||
}>
|
||||
total: number
|
||||
creditsUsed: number
|
||||
}
|
||||
}
|
||||
|
||||
export type FirecrawlResponse = ScrapeResponse | SearchResponse | FirecrawlCrawlResponse
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
* which runs JavaScript code in a secure sandbox.
|
||||
*/
|
||||
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
|
||||
import { ToolTester } from '../__test-utils__/test-tools'
|
||||
import { functionExecuteTool } from './execute'
|
||||
import { ToolTester } from '@/tools/__test-utils__/test-tools'
|
||||
import { functionExecuteTool } from '@/tools/function/execute'
|
||||
|
||||
describe('Function Execute Tool', () => {
|
||||
let tester: ToolTester
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { CodeExecutionInput, CodeExecutionOutput } from './types'
|
||||
import type { CodeExecutionInput, CodeExecutionOutput } from '@/tools/function/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const DEFAULT_TIMEOUT = 10000 // 10 seconds
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import { functionExecuteTool } from './execute'
|
||||
import { functionExecuteTool } from '@/tools/function/execute'
|
||||
|
||||
export { functionExecuteTool }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ToolResponse } from '../types'
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
export interface CodeExecutionInput {
|
||||
code: Array<{ content: string; id: string }> | string
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { CreateCommentParams, CreateCommentResponse } from './types'
|
||||
import type { CreateCommentParams, CreateCommentResponse } from '@/tools/github/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const commentTool: ToolConfig<CreateCommentParams, CreateCommentResponse> = {
|
||||
id: 'github_comment',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { commentTool } from './comment'
|
||||
import { latestCommitTool } from './latest_commit'
|
||||
import { prTool } from './pr'
|
||||
import { repoInfoTool } from './repo_info'
|
||||
import { commentTool } from '@/tools/github/comment'
|
||||
import { latestCommitTool } from '@/tools/github/latest_commit'
|
||||
import { prTool } from '@/tools/github/pr'
|
||||
import { repoInfoTool } from '@/tools/github/repo_info'
|
||||
|
||||
export const githubCommentTool = commentTool
|
||||
export const githubLatestCommitTool = latestCommitTool
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { LatestCommitParams, LatestCommitResponse } from './types'
|
||||
import type { LatestCommitParams, LatestCommitResponse } from '@/tools/github/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const latestCommitTool: ToolConfig<LatestCommitParams, LatestCommitResponse> = {
|
||||
id: 'github_latest_commit',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { PROperationParams, PullRequestResponse } from './types'
|
||||
import type { PROperationParams, PullRequestResponse } from '@/tools/github/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const prTool: ToolConfig<PROperationParams, PullRequestResponse> = {
|
||||
id: 'github_pr',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { BaseGitHubParams, RepoInfoResponse } from './types'
|
||||
import type { BaseGitHubParams, RepoInfoResponse } from '@/tools/github/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const repoInfoTool: ToolConfig<BaseGitHubParams, RepoInfoResponse> = {
|
||||
id: 'github_repo_info',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ToolResponse } from '../types'
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
// Base parameters shared by all GitHub operations
|
||||
export interface BaseGitHubParams {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { GmailSendParams, GmailToolResponse } from './types'
|
||||
import type { GmailSendParams, GmailToolResponse } from '@/tools/gmail/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const GMAIL_API_BASE = 'https://gmail.googleapis.com/gmail/v1/users/me'
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { gmailDraftTool } from './draft'
|
||||
import { gmailReadTool } from './read'
|
||||
import { gmailSearchTool } from './search'
|
||||
import { gmailSendTool } from './send'
|
||||
import { gmailDraftTool } from '@/tools/gmail/draft'
|
||||
import { gmailReadTool } from '@/tools/gmail/read'
|
||||
import { gmailSearchTool } from '@/tools/gmail/search'
|
||||
import { gmailSendTool } from '@/tools/gmail/send'
|
||||
|
||||
export { gmailSendTool, gmailReadTool, gmailSearchTool, gmailDraftTool }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { GmailMessage, GmailReadParams, GmailToolResponse } from './types'
|
||||
import type { GmailMessage, GmailReadParams, GmailToolResponse } from '@/tools/gmail/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const GMAIL_API_BASE = 'https://gmail.googleapis.com/gmail/v1/users/me'
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { GmailSearchParams, GmailToolResponse } from './types'
|
||||
import type { GmailSearchParams, GmailToolResponse } from '@/tools/gmail/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const GMAIL_API_BASE = 'https://gmail.googleapis.com/gmail/v1/users/me'
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { GmailSendParams, GmailToolResponse } from './types'
|
||||
import type { GmailSendParams, GmailToolResponse } from '@/tools/gmail/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const GMAIL_API_BASE = 'https://gmail.googleapis.com/gmail/v1/users/me'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ToolResponse } from '../types'
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
// Base parameters shared by all operations
|
||||
interface BaseGmailParams {
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import { searchTool } from './search'
|
||||
import { searchTool } from '@/tools/google/search'
|
||||
|
||||
export { searchTool }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { GoogleSearchParams, GoogleSearchResponse } from './types'
|
||||
import type { GoogleSearchParams, GoogleSearchResponse } from '@/tools/google/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const searchTool: ToolConfig<GoogleSearchParams, GoogleSearchResponse> = {
|
||||
id: 'google_search',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ToolResponse } from '../types'
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
export interface GoogleSearchParams {
|
||||
query: string
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import {
|
||||
CALENDAR_API_BASE,
|
||||
type GoogleCalendarApiEventResponse,
|
||||
type GoogleCalendarCreateParams,
|
||||
type GoogleCalendarCreateResponse,
|
||||
type GoogleCalendarEventRequestBody,
|
||||
} from './types'
|
||||
} from '@/tools/google_calendar/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const createTool: ToolConfig<GoogleCalendarCreateParams, GoogleCalendarCreateResponse> = {
|
||||
id: 'google_calendar_create',
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import {
|
||||
CALENDAR_API_BASE,
|
||||
type GoogleCalendarApiEventResponse,
|
||||
type GoogleCalendarGetParams,
|
||||
type GoogleCalendarGetResponse,
|
||||
} from './types'
|
||||
} from '@/tools/google_calendar/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const getTool: ToolConfig<GoogleCalendarGetParams, GoogleCalendarGetResponse> = {
|
||||
id: 'google_calendar_get',
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { createTool } from './create'
|
||||
import { getTool } from './get'
|
||||
import { inviteTool } from './invite'
|
||||
import { listTool } from './list'
|
||||
import { quickAddTool } from './quick_add'
|
||||
import { createTool } from '@/tools/google_calendar/create'
|
||||
import { getTool } from '@/tools/google_calendar/get'
|
||||
import { inviteTool } from '@/tools/google_calendar/invite'
|
||||
import { listTool } from '@/tools/google_calendar/list'
|
||||
import { quickAddTool } from '@/tools/google_calendar/quick_add'
|
||||
|
||||
export const googleCalendarCreateTool = createTool
|
||||
export const googleCalendarGetTool = getTool
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import {
|
||||
CALENDAR_API_BASE,
|
||||
type GoogleCalendarInviteParams,
|
||||
type GoogleCalendarInviteResponse,
|
||||
} from './types'
|
||||
} from '@/tools/google_calendar/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const inviteTool: ToolConfig<GoogleCalendarInviteParams, GoogleCalendarInviteResponse> = {
|
||||
id: 'google_calendar_invite',
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import {
|
||||
CALENDAR_API_BASE,
|
||||
type GoogleCalendarApiEventResponse,
|
||||
type GoogleCalendarApiListResponse,
|
||||
type GoogleCalendarListParams,
|
||||
type GoogleCalendarListResponse,
|
||||
} from './types'
|
||||
} from '@/tools/google_calendar/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const listTool: ToolConfig<GoogleCalendarListParams, GoogleCalendarListResponse> = {
|
||||
id: 'google_calendar_list',
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import {
|
||||
CALENDAR_API_BASE,
|
||||
type GoogleCalendarQuickAddParams,
|
||||
type GoogleCalendarQuickAddResponse,
|
||||
} from './types'
|
||||
} from '@/tools/google_calendar/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const quickAddTool: ToolConfig<
|
||||
GoogleCalendarQuickAddParams,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ToolResponse } from '../types'
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
export const CALENDAR_API_BASE = 'https://www.googleapis.com/calendar/v3'
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import {
|
||||
CALENDAR_API_BASE,
|
||||
type GoogleCalendarToolResponse,
|
||||
type GoogleCalendarUpdateParams,
|
||||
} from './types'
|
||||
} from '@/tools/google_calendar/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const updateTool: ToolConfig<GoogleCalendarUpdateParams, GoogleCalendarToolResponse> = {
|
||||
id: 'google_calendar_update',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { GoogleDocsCreateResponse, GoogleDocsToolParams } from './types'
|
||||
import type { GoogleDocsCreateResponse, GoogleDocsToolParams } from '@/tools/google_docs/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('GoogleDocsCreateTool')
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createTool } from './create'
|
||||
import { readTool } from './read'
|
||||
import { writeTool } from './write'
|
||||
import { createTool } from '@/tools/google_docs/create'
|
||||
import { readTool } from '@/tools/google_docs/read'
|
||||
import { writeTool } from '@/tools/google_docs/write'
|
||||
|
||||
export const googleDocsReadTool = readTool
|
||||
export const googleDocsWriteTool = writeTool
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { GoogleDocsReadResponse, GoogleDocsToolParams } from './types'
|
||||
import type { GoogleDocsReadResponse, GoogleDocsToolParams } from '@/tools/google_docs/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const readTool: ToolConfig<GoogleDocsToolParams, GoogleDocsReadResponse> = {
|
||||
id: 'google_docs_read',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ToolResponse } from '../types'
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
export interface GoogleDocsMetadata {
|
||||
documentId: string
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { GoogleDocsToolParams, GoogleDocsWriteResponse } from './types'
|
||||
import type { GoogleDocsToolParams, GoogleDocsWriteResponse } from '@/tools/google_docs/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const writeTool: ToolConfig<GoogleDocsToolParams, GoogleDocsWriteResponse> = {
|
||||
id: 'google_docs_write',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { GoogleDriveToolParams, GoogleDriveUploadResponse } from './types'
|
||||
import type { GoogleDriveToolParams, GoogleDriveUploadResponse } from '@/tools/google_drive/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const createFolderTool: ToolConfig<GoogleDriveToolParams, GoogleDriveUploadResponse> = {
|
||||
id: 'google_drive_create_folder',
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { GoogleDriveGetContentResponse, GoogleDriveToolParams } from './types'
|
||||
import { DEFAULT_EXPORT_FORMATS, GOOGLE_WORKSPACE_MIME_TYPES } from './utils'
|
||||
import type {
|
||||
GoogleDriveGetContentResponse,
|
||||
GoogleDriveToolParams,
|
||||
} from '@/tools/google_drive/types'
|
||||
import { DEFAULT_EXPORT_FORMATS, GOOGLE_WORKSPACE_MIME_TYPES } from '@/tools/google_drive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('GoogleDriveGetContentTool')
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createFolderTool } from './create_folder'
|
||||
import { getContentTool } from './get_content'
|
||||
import { listTool } from './list'
|
||||
import { uploadTool } from './upload'
|
||||
import { createFolderTool } from '@/tools/google_drive/create_folder'
|
||||
import { getContentTool } from '@/tools/google_drive/get_content'
|
||||
import { listTool } from '@/tools/google_drive/list'
|
||||
import { uploadTool } from '@/tools/google_drive/upload'
|
||||
|
||||
export const googleDriveCreateFolderTool = createFolderTool
|
||||
export const googleDriveGetContentTool = getContentTool
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { GoogleDriveListResponse, GoogleDriveToolParams } from './types'
|
||||
import type { GoogleDriveListResponse, GoogleDriveToolParams } from '@/tools/google_drive/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const listTool: ToolConfig<GoogleDriveToolParams, GoogleDriveListResponse> = {
|
||||
id: 'google_drive_list',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ToolResponse } from '../types'
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
export interface GoogleDriveFile {
|
||||
id: string
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { GoogleDriveToolParams, GoogleDriveUploadResponse } from './types'
|
||||
import { GOOGLE_WORKSPACE_MIME_TYPES, SOURCE_MIME_TYPES } from './utils'
|
||||
import type { GoogleDriveToolParams, GoogleDriveUploadResponse } from '@/tools/google_drive/types'
|
||||
import { GOOGLE_WORKSPACE_MIME_TYPES, SOURCE_MIME_TYPES } from '@/tools/google_drive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('GoogleDriveUploadTool')
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { GoogleSheetsAppendResponse, GoogleSheetsToolParams } from './types'
|
||||
import type {
|
||||
GoogleSheetsAppendResponse,
|
||||
GoogleSheetsToolParams,
|
||||
} from '@/tools/google_sheets/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const appendTool: ToolConfig<GoogleSheetsToolParams, GoogleSheetsAppendResponse> = {
|
||||
id: 'google_sheets_append',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { appendTool } from './append'
|
||||
import { readTool } from './read'
|
||||
import { updateTool } from './update'
|
||||
import { writeTool } from './write'
|
||||
import { appendTool } from '@/tools/google_sheets/append'
|
||||
import { readTool } from '@/tools/google_sheets/read'
|
||||
import { updateTool } from '@/tools/google_sheets/update'
|
||||
import { writeTool } from '@/tools/google_sheets/write'
|
||||
|
||||
export const googleSheetsReadTool = readTool
|
||||
export const googleSheetsWriteTool = writeTool
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { GoogleSheetsReadResponse, GoogleSheetsToolParams } from './types'
|
||||
import type { GoogleSheetsReadResponse, GoogleSheetsToolParams } from '@/tools/google_sheets/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const readTool: ToolConfig<GoogleSheetsToolParams, GoogleSheetsReadResponse> = {
|
||||
id: 'google_sheets_read',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ToolResponse } from '../types'
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
export interface GoogleSheetsRange {
|
||||
sheetId?: number
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { GoogleSheetsToolParams, GoogleSheetsUpdateResponse } from './types'
|
||||
import type {
|
||||
GoogleSheetsToolParams,
|
||||
GoogleSheetsUpdateResponse,
|
||||
} from '@/tools/google_sheets/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const updateTool: ToolConfig<GoogleSheetsToolParams, GoogleSheetsUpdateResponse> = {
|
||||
id: 'google_sheets_update',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ToolConfig } from '../types'
|
||||
import type { GoogleSheetsToolParams, GoogleSheetsWriteResponse } from './types'
|
||||
import type { GoogleSheetsToolParams, GoogleSheetsWriteResponse } from '@/tools/google_sheets/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const writeTool: ToolConfig<GoogleSheetsToolParams, GoogleSheetsWriteResponse> = {
|
||||
id: 'google_sheets_write',
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import { requestTool } from './request'
|
||||
import { requestTool } from '@/tools/http/request'
|
||||
|
||||
export { requestTool }
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
* to make HTTP requests to external APIs and services.
|
||||
*/
|
||||
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
|
||||
import { mockHttpResponses } from '../__test-utils__/mock-data'
|
||||
import { ToolTester } from '../__test-utils__/test-tools'
|
||||
import { requestTool } from './request'
|
||||
import { mockHttpResponses } from '@/tools/__test-utils__/mock-data'
|
||||
import { ToolTester } from '@/tools/__test-utils__/test-tools'
|
||||
import { requestTool } from '@/tools/http/request'
|
||||
|
||||
process.env.VITEST = 'true'
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ import { env } from '@/lib/env'
|
||||
import { isTest } from '@/lib/environment'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { getBaseUrl } from '@/lib/urls/utils'
|
||||
import type { HttpMethod, TableRow, ToolConfig } from '../types'
|
||||
import type { RequestParams, RequestResponse } from './types'
|
||||
import type { RequestParams, RequestResponse } from '@/tools/http/types'
|
||||
import type { HttpMethod, TableRow, ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('HTTPRequestTool')
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { HttpMethod, TableRow, ToolResponse } from '../types'
|
||||
import type { HttpMethod, TableRow, ToolResponse } from '@/tools/types'
|
||||
|
||||
export interface RequestParams {
|
||||
url: string
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user