Skip to content
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 37 additions & 48 deletions packages/components/nodes/tools/ExaSearch/ExaSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,41 +50,39 @@ class ExaSearch_Tools implements INode {
type: 'options',
options: [
{
label: 'keyword',
name: 'keyword'
label: 'auto',
name: 'auto'
},
{
label: 'neural',
name: 'neural'
label: 'fast',
name: 'fast'
},
{
label: 'auto',
name: 'auto',
description: 'decides between keyword and neural'
label: 'instant',
name: 'instant'
},
{
label: 'deep',
name: 'deep'
}
],
optional: true,
additionalParams: true
},
{
label: 'Use Auto Prompt',
name: 'useAutoprompt',
type: 'boolean',
optional: true,
additionalParams: true,
description: 'If true, your query will be converted to a Exa query. Default false.'
},
{
label: 'Category (Beta)',
label: 'Category',
name: 'category',
type: 'options',
description:
'A data category to focus on, with higher comprehensivity and data cleanliness. Categories right now include company, research paper, news, github, tweet, movie, song, personal site, and pdf',
description: 'A data category to focus on.',
options: [
{
label: 'company',
name: 'company'
},
{
label: 'people',
name: 'people'
},
{
label: 'research paper',
name: 'research paper'
Expand All @@ -93,34 +91,10 @@ class ExaSearch_Tools implements INode {
label: 'news',
name: 'news'
},
{
label: 'github',
name: 'github'
},
{
label: 'tweet',
name: 'tweet'
},
{
label: 'movie',
name: 'movie'
},
{
label: 'song',
name: 'song'
},
{
label: 'pdf',
name: 'pdf'
},
{
label: 'personal site',
name: 'personal site'
},
{
label: 'linkedin profile',
name: 'linkedin profile'
},
{
label: 'financial report',
name: 'financial report'
Expand All @@ -129,6 +103,15 @@ class ExaSearch_Tools implements INode {
optional: true,
additionalParams: true
},
{
label: 'Max Age Hours',
name: 'maxAgeHours',
type: 'number',
optional: true,
additionalParams: true,
description:
'Freshness control. 0 = always crawl, -1 = cache only, 24 = cache if less than 24h old.'
},
{
label: 'Include Domains',
name: 'includeDomains',
Expand Down Expand Up @@ -200,9 +183,9 @@ class ExaSearch_Tools implements INode {
async init(nodeData: INodeData, _: string, options: ICommonObject): Promise<any> {
const description = nodeData.inputs?.description as string
const numResults = nodeData.inputs?.numResults as string
const type = nodeData.inputs?.type as 'keyword' | 'neural' | 'auto' | undefined
const useAutoprompt = nodeData.inputs?.useAutoprompt as boolean
const type = nodeData.inputs?.type as string | undefined
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The type for type has been generalized to string | undefined, which reduces type safety. Since the supported search types are now a fixed set, it is better to use a union of the allowed string literals to maintain compile-time validation.

Suggested change
const type = nodeData.inputs?.type as string | undefined
const type = nodeData.inputs?.type as 'auto' | 'fast' | 'instant' | 'deep' | undefined

const category = nodeData.inputs?.category as string
const maxAgeHours = nodeData.inputs?.maxAgeHours as string
const includeDomains = nodeData.inputs?.includeDomains as string
const excludeDomains = nodeData.inputs?.excludeDomains as string
const startCrawlDate = nodeData.inputs?.startCrawlDate as string
Expand All @@ -213,19 +196,25 @@ class ExaSearch_Tools implements INode {
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
const exaSearchApiKey = getCredentialParam('exaSearchApiKey', credentialData, nodeData)

const client = new Exa(exaSearchApiKey)
;(client as any).headers = {
...(client as any).headers,
'x-exa-integration': 'flowise-integration'
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The Exa client from the exa-js library does not typically expose or utilize a headers property on the instance for its requests. The internal request method in the SDK usually constructs headers dynamically using only the apiKey. Consequently, setting (client as any).headers is likely non-functional, and the x-exa-integration header will not be sent to the API.

If the SDK version used does not support custom headers in the constructor or via a public property, this integration tracking might not be achievable through the SDK instance directly. You should verify if the header is actually being sent in your tests.


const tool = new ExaSearchResults({
client: new Exa(exaSearchApiKey),
client,
searchArgs: {
numResults: numResults ? parseFloat(numResults) : undefined,
type: type || undefined,
useAutoprompt: useAutoprompt || undefined,
type: (type as any) || undefined,
category: (category as any) || undefined,
includeDomains: includeDomains ? includeDomains.split(',') : undefined,
excludeDomains: excludeDomains ? excludeDomains.split(',') : undefined,
Comment on lines 204 to 205
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

When splitting domains by comma, users might include spaces (e.g., "example.com, test.com"). It is recommended to trim each domain string to ensure the API receives clean values without leading or trailing whitespace. This approach of using simple, chained operations improves readability and reduces potential errors.

Suggested change
includeDomains: includeDomains ? includeDomains.split(',') : undefined,
excludeDomains: excludeDomains ? excludeDomains.split(',') : undefined,
includeDomains: includeDomains ? includeDomains.split(',').map((d) => d.trim()) : undefined,
excludeDomains: excludeDomains ? excludeDomains.split(',').map((d) => d.trim()) : undefined,
References
  1. Prioritize code readability and understandability over conciseness. A series of simple, chained operations can be preferable to a single, more complex one if it improves understandability and reduces the potential for future errors.

startCrawlDate: startCrawlDate || undefined,
endCrawlDate: endCrawlDate || undefined,
startPublishedDate: startPublishedDate || undefined,
endPublishedDate: endPublishedDate || undefined
endPublishedDate: endPublishedDate || undefined,
...(maxAgeHours ? { maxAgeHours: parseFloat(maxAgeHours) } : {})
}
})

Expand Down