Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
74 changes: 57 additions & 17 deletions apps/docs/content/docs/integrations/firecrawl.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -157,27 +157,64 @@ Search for information on the web using Firecrawl
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `query` | string | Yes | The search query to use |
| `sources` | array | No | Which result sets to search: any of "web", "news", "images". Determines which arrays appear on the output. Defaults to \["web"\]. |
| `limit` | number | No | Maximum number of results to return per source |
| `apiKey` | string | Yes | Firecrawl API key |

#### Output

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `data` | array | Search results data with scraped content and metadata |
| ↳ `title` | string | Search result title from search engine |
| ↳ `description` | string | Search result description/snippet from search engine |
| ↳ `url` | string | URL of the search result |
| ↳ `markdown` | string | Page content in markdown; returned only when scraping was requested via the hidden scrapeOptions input |
| ↳ `html` | string | Processed HTML content; returned only when "html" is among the scrape formats requested via the hidden scrapeOptions input |
| ↳ `rawHtml` | string | Unprocessed raw HTML; returned only when "rawHtml" is among the scrape formats requested via the hidden scrapeOptions input |
| ↳ `links` | array | Links found on the page; returned only when "links" is among the scrape formats requested via the hidden scrapeOptions input |
| ↳ `screenshot` | string | Screenshot URL \(expires after 24 hours\); returned only when "screenshot" is among the scrape formats requested via the hidden scrapeOptions input |
| ↳ `metadata` | object | Metadata about the search result page |
| ↳ `title` | string | Page title |
| ↳ `description` | string | Page meta description |
| ↳ `sourceURL` | string | Original source URL |
| ↳ `statusCode` | number | HTTP status code |
| ↳ `error` | string | Error message if scrape failed |
| `data` | object | Search results keyed by source \(web, news, images\), each with optional scraped content and metadata |
Comment thread
waleedlatif1 marked this conversation as resolved.
| ↳ `web` | array | Web search results |
| ↳ `title` | string | Search result title from search engine |
| ↳ `description` | string | Search result description/snippet from search engine |
| ↳ `url` | string | URL of the search result |
| ↳ `position` | number | Position of the result |
| ↳ `markdown` | string | Page content in markdown; returned only when scraping was requested via the hidden scrapeOptions input |
| ↳ `html` | string | Processed HTML content; returned only when "html" is among the scrape formats requested via the hidden scrapeOptions input |
| ↳ `rawHtml` | string | Unprocessed raw HTML; returned only when "rawHtml" is among the scrape formats requested via the hidden scrapeOptions input |
| ↳ `links` | array | Links found on the page; returned only when "links" is among the scrape formats requested via the hidden scrapeOptions input |
| ↳ `screenshot` | string | Screenshot URL \(expires after 24 hours\); returned only when "screenshot" is among the scrape formats requested via the hidden scrapeOptions input |
| ↳ `audio` | string | Signed URL to the extracted MP3 audio \(expires after 1 hour\); returned only when "audio" is among the requested scrape formats |
| ↳ `video` | string | Signed URL to the extracted video \(expires after 1 hour\); returned only when "video" is among the requested scrape formats |
| ↳ `category` | string | Category the result was matched under, when the request narrowed by category |
| ↳ `metadata` | object | Metadata about the search result page; present only when the result was scraped |
| ↳ `title` | string | Page title |
| ↳ `description` | string | Page meta description |
| ↳ `sourceURL` | string | The originally requested URL. Differs from `url` when the request was redirected. |
| ↳ `url` | string | The final URL of the page after all redirects were followed |
| ↳ `statusCode` | number | HTTP status code |
| ↳ `error` | string | Error message if scrape failed |
| ↳ `news` | array | News search results \(present only when "news" is among the requested sources\) |
| ↳ `title` | string | Title of the article |
| ↳ `snippet` | string | Snippet from the article |
| ↳ `url` | string | URL of the article |
| ↳ `date` | string | Publication date of the article |
| ↳ `imageUrl` | string | Thumbnail image URL for the article |
| ↳ `position` | number | Position of the article |
| ↳ `markdown` | string | Article content in markdown; returned only when scraping was requested via the hidden scrapeOptions input |
| ↳ `html` | string | Processed HTML content; returned only when "html" is among the requested scrape formats |
| ↳ `rawHtml` | string | Unprocessed raw HTML; returned only when "rawHtml" is among the requested scrape formats |
| ↳ `links` | array | Links found on the article page; returned only when "links" was requested |
| ↳ `screenshot` | string | Screenshot URL \(expires after 24 hours\); returned only when requested |
| ↳ `audio` | string | Signed URL to the extracted MP3 audio \(expires after 1 hour\); returned only when "audio" is among the requested scrape formats |
| ↳ `video` | string | Signed URL to the extracted video \(expires after 1 hour\); returned only when "video" is among the requested scrape formats |
| ↳ `category` | string | Category the article was matched under, when the request narrowed by category |
| ↳ `metadata` | object | Metadata about the search result page; present only when the result was scraped |
| ↳ `title` | string | Page title |
| ↳ `description` | string | Page meta description |
| ↳ `sourceURL` | string | The originally requested URL. Differs from `url` when the request was redirected. |
| ↳ `url` | string | The final URL of the page after all redirects were followed |
| ↳ `statusCode` | number | HTTP status code |
| ↳ `error` | string | Error message if scrape failed |
| ↳ `images` | array | Image search results \(present only when "images" is among the requested sources\) |
| ↳ `title` | string | Title from the search result |
| ↳ `imageUrl` | string | Direct URL of the image |
| ↳ `imageWidth` | number | Image width in pixels |
| ↳ `imageHeight` | number | Image height in pixels |
| ↳ `url` | string | URL of the page containing the image |
| ↳ `position` | number | Position of the result |

### Firecrawl Crawl

Expand Down Expand Up @@ -282,15 +319,18 @@ Get a complete list of URLs from any website quickly and reliably. Useful for di
| `includeSubdomains` | boolean | No | Whether to include URLs from subdomains \(default: true\) |
| `ignoreQueryParameters` | boolean | No | Exclude URLs containing query strings \(default: true\) |
| `limit` | number | No | Maximum number of links to return \(e.g., 100, 1000, 5000\). Max: 100,000, default: 5,000 |
| `timeout` | number | No | Request timeout in milliseconds |
| `mapTimeout` | number | No | Firecrawl's own map deadline in milliseconds, sent as the request body's `timeout`. Named `mapTimeout` because a tool param called `timeout` is consumed as the outbound fetch deadline instead of reaching Firecrawl. |
Comment thread
waleedlatif1 marked this conversation as resolved.
| `apiKey` | string | Yes | Firecrawl API key |

#### Output

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `success` | boolean | Whether the mapping operation was successful |
| `links` | array | Array of discovered URLs from the website |
| `links` | array | Discovered pages. Each entry is an object with the URL plus, when Firecrawl has them, the page title and description. |
| ↳ `url` | string | Discovered URL |
| ↳ `title` | string | Title of the page, when available |
| ↳ `description` | string | Description of the page, when available |

### Firecrawl Extract

Expand Down
19 changes: 16 additions & 3 deletions apps/docs/content/docs/integrations/serper.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,31 @@ A powerful web search tool that provides access to Google search results through

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `searchResults` | array | Search results with titles, links, snippets, and type-specific metadata \(date for news, rating for places, imageUrl for images, duration/source for videos, price/source for shopping\) |
| `searchResults` | array | Search results with titles, links, snippets, and type-specific metadata \(date/source for news, rating/ratingCount/address/category for places, imageUrl for images, duration/source for videos, price/source for shopping\) |
| ↳ `title` | string | Result title |
| ↳ `link` | string | Result URL |
| ↳ `snippet` | string | Result description/snippet |
| ↳ `link` | string | Result URL. Absent on places results, which Google returns without a link. |
| ↳ `snippet` | string | Result description/snippet. Absent on places results. |
| ↳ `position` | number | Position in search results |
| ↳ `date` | string | Publication date \(news/videos\) |
| ↳ `imageUrl` | string | Image URL \(images/news/shopping\) |
| ↳ `source` | string | Source name \(news/videos/shopping\) |
| ↳ `rating` | number | Rating \(places\) |
| ↳ `ratingCount` | number | Number of reviews \(places\) |
| ↳ `address` | string | Address \(places\) |
| ↳ `category` | string | Business category \(places\) |
| ↳ `phoneNumber` | string | Contact phone number \(places\) |
| ↳ `website` | string | Business website \(places\) |
| ↳ `latitude` | number | Latitude coordinate \(places\) |
| ↳ `longitude` | number | Longitude coordinate \(places\) |
| ↳ `cid` | string | Google CID identifier \(places\) |
| ↳ `price` | string | Price \(shopping\) |
| ↳ `duration` | string | Duration \(videos\) |
| `peopleAlsoAsk` | array | Related questions Google surfaces on the web search vertical |
| ↳ `question` | string | The question that was asked |
| ↳ `snippet` | string | A snippet of the answer |
| ↳ `title` | string | Title of the source page |
| ↳ `link` | string | URL of the source page |
| `relatedSearches` | array | Suggested follow-up queries Google surfaces on the web search vertical |
| ↳ `query` | string | Suggested search query |


80 changes: 77 additions & 3 deletions apps/sim/blocks/blocks/firecrawl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,32 @@ import type { FirecrawlResponse } from '@/tools/firecrawl/types'
/** The document being parsed, whether it was uploaded or passed in by reference. */
const DOCUMENT_FIELD = ['fileUpload', 'fileReference'] as const

const FIRECRAWL_SEARCH_SOURCES = ['web', 'news', 'images'] as const

type FirecrawlSearchSource = (typeof FIRECRAWL_SEARCH_SOURCES)[number]

/**
* The multi-select stores its value as an array, but a saved workflow can still hold the
* JSON-string form an earlier revision wrote. Unknown entries are dropped rather than forwarded,
* since Firecrawl rejects a source it does not know.
*/
function parseSearchSources(value: unknown): FirecrawlSearchSource[] | undefined {
let raw: unknown = value
if (typeof raw === 'string') {
if (raw.trim() === '') return undefined
try {
raw = JSON.parse(raw)
} catch {
raw = [raw]
}
}
if (!Array.isArray(raw)) return undefined
const sources = raw.filter((entry): entry is FirecrawlSearchSource =>
FIRECRAWL_SEARCH_SOURCES.includes(entry as FirecrawlSearchSource)
)
return sources.length > 0 ? sources : undefined
}

export const FirecrawlBlock: BlockConfig<FirecrawlResponse> = {
type: 'firecrawl',
name: 'Firecrawl',
Expand Down Expand Up @@ -341,6 +367,17 @@ Example 2 - Product Data:
value: ['crawl', 'map', 'search'],
},
},
{
id: 'mapTimeout',
title: 'Map Timeout (ms)',
type: 'short-input',
placeholder: '30000',
description: "Firecrawl's own deadline for the map request. Leave empty for no timeout.",
condition: {
field: 'operation',
value: 'map',
},
},
{
id: 'includeTags',
title: 'Include Tags',
Expand Down Expand Up @@ -429,6 +466,24 @@ Example 2 - Product Data:
},
required: true,
},
{
id: 'sources',
title: 'Sources',
type: 'dropdown',
multiSelect: true,
placeholder: 'Web',
description:
'Which result sets to search. Determines the arrays present on the output. Defaults to Web.',
options: [
{ label: 'Web', id: 'web' },
{ label: 'News', id: 'news' },
{ label: 'Images', id: 'images' },
],
condition: {
field: 'operation',
value: 'search',
},
},
{
id: 'apiKey',
title: 'API Key',
Expand Down Expand Up @@ -550,22 +605,33 @@ Example 2 - Product Data:
if (mobile != null) result.mobile = mobile
break

case 'search':
case 'search': {
if (query) result.query = query
if (timeout) result.timeout = Number.parseInt(timeout)
if (limit) result.limit = Number.parseInt(limit)
const sources = parseSearchSources(params.sources)
if (sources) result.sources = sources
break
}

case 'crawl':
if (url) result.url = url
if (limit) result.limit = Number.parseInt(limit)
if (onlyMainContent != null) result.onlyMainContent = onlyMainContent
break

case 'map':
case 'map': {
if (url) result.url = url
if (limit) result.limit = Number.parseInt(limit)
/**
* Forwarded raw so the tool's own guard decides: it keeps an explicit `0` and drops a
* blank field, which a `Number.parseInt` here would collapse into `NaN`.
*/
if (params.mapTimeout != null && params.mapTimeout !== '') {
result.mapTimeout = params.mapTimeout
}
break
}

case 'extract':
if (urls) {
Expand Down Expand Up @@ -730,10 +796,15 @@ Example 2 - Product Data:
urls: { type: 'json', description: 'Array of URLs for extraction or batch scraping' },
jobId: { type: 'string', description: 'Job ID for status/cancel operations' },
query: { type: 'string', description: 'Search query terms' },
sources: { type: 'json', description: 'Search result sources: web, news and/or images' },
prompt: { type: 'string', description: 'Extraction prompt' },
limit: { type: 'string', description: 'Result/page limit' },
formats: { type: 'json', description: 'Output formats array' },
timeout: { type: 'number', description: 'Request timeout in ms' },
mapTimeout: {
type: 'number',
description: "Firecrawl's own deadline for a map request, in ms",
},
waitFor: { type: 'number', description: 'Wait time before scraping in ms' },
mobile: { type: 'boolean', description: 'Use mobile emulation' },
onlyMainContent: { type: 'boolean', description: 'Extract only main content' },
Expand Down Expand Up @@ -792,7 +863,10 @@ Example 2 - Product Data:
invalidURLs: { type: 'json', description: 'URLs skipped because they were invalid' },
// Map output
success: { type: 'boolean', description: 'Operation success status' },
links: { type: 'json', description: 'Discovered URLs array' },
links: {
type: 'json',
description: 'Discovered pages as objects with url and optional title/description',
},
// Extract output
sources: { type: 'json', description: 'Data sources array' },
tokensUsed: { type: 'number', description: 'Tokens consumed by the extract job' },
Expand Down
13 changes: 1 addition & 12 deletions apps/sim/blocks/blocks/langsmith.ts
Original file line number Diff line number Diff line change
Expand Up @@ -385,22 +385,11 @@ Common patch fields: outputs, end_time, status, error`,
}

if (params.operation === 'langsmith_create_feedback') {
const parseScore = (value: unknown) => {
if (value === undefined || value === null || value === '') {
return undefined
}
const parsed = Number(value)
if (Number.isNaN(parsed)) {
throw new Error(`Invalid score: "${value}" is not a number`)
}
return parsed
}

return {
apiKey: params.apiKey,
runId: params.runId,
key: params.key,
score: parseScore(params.score),
score: params.score,
value: params.value,
comment: params.comment,
correction: parseJsonValue(params.correction, 'correction'),
Expand Down
10 changes: 6 additions & 4 deletions apps/sim/blocks/blocks/qdrant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,9 +257,11 @@ Return ONLY the JSON object.`,
},

outputs: {
matches: { type: 'json', description: 'Search matches' },
upsertedCount: { type: 'number', description: 'Upserted count' },
data: { type: 'json', description: 'Response data' },
data: {
type: 'json',
description:
'Result payload: matched points for search, fetched points for fetch, or the update result for upsert',
Comment thread
waleedlatif1 marked this conversation as resolved.
},
status: { type: 'string', description: 'Operation status' },
},
}
Expand Down Expand Up @@ -340,7 +342,7 @@ export const QdrantBlockMeta = {
name: 'upsert-points',
description: 'Insert or update vector points with payload metadata into a Qdrant collection.',
content:
'# Upsert Points\n\nLoad vectors into a Qdrant collection.\n\n## Steps\n1. Use the Upsert operation with the Qdrant URL, Collection name, and API Key.\n2. Provide Points as a JSON array, each with an id, a vector matching the collection dimension, and an optional payload of metadata for later filtering.\n3. Confirm the upserted count from the response.\n\n## Output\nReport how many points were upserted into which collection and surface any payload validation issues.',
'# Upsert Points\n\nLoad vectors into a Qdrant collection.\n\n## Steps\n1. Use the Upsert operation with the Qdrant URL, Collection name, and API Key.\n2. Provide Points as a JSON array, each with an id, a vector matching the collection dimension, and an optional payload of metadata for later filtering.\n3. Confirm the operation succeeded from `status` and read `data.operation_id` and `data.status` in the response.\n\n## Output\nReport the operation id and its status (`acknowledged` or `completed`) for the collection written to, and surface any payload validation issues. Qdrant does not return a count of upserted points, so report the number of points that were sent instead of inventing one.',
},
{
name: 'search-vectors',
Expand Down
Loading
Loading