From 6e98ef492ee17c41a8307811fa8466f5e60744c4 Mon Sep 17 00:00:00 2001 From: Theodore Li Date: Thu, 21 May 2026 19:27:28 -0700 Subject: [PATCH 1/3] fix(db): disable statement_timeout for migrations --- packages/db/scripts/migrate.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/db/scripts/migrate.ts b/packages/db/scripts/migrate.ts index 4918b572cf3..d8449a5775a 100644 --- a/packages/db/scripts/migrate.ts +++ b/packages/db/scripts/migrate.ts @@ -12,6 +12,7 @@ if (!url) { const client = postgres(url, { max: 1, connect_timeout: 10 }) try { + await client`SET statement_timeout = 0` await migrate(drizzle(client), { migrationsFolder: './migrations' }) console.log('Migrations applied successfully.') } catch (error) { From 1ca4dbac3b2c8a35c3adced90d05a7cfdf6e0449 Mon Sep 17 00:00:00 2001 From: Theodore Li Date: Thu, 21 May 2026 19:32:38 -0700 Subject: [PATCH 2/3] fix(ci): route migration workflow through guarded migrate.ts --- .github/workflows/migrations.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/migrations.yml b/.github/workflows/migrations.yml index daf41a0d984..4a6aab428ad 100644 --- a/.github/workflows/migrations.yml +++ b/.github/workflows/migrations.yml @@ -39,4 +39,4 @@ jobs: working-directory: ./packages/db env: DATABASE_URL: ${{ github.ref == 'refs/heads/main' && secrets.DATABASE_URL || github.ref == 'refs/heads/dev' && secrets.DEV_DATABASE_URL || secrets.STAGING_DATABASE_URL }} - run: bunx drizzle-kit migrate --config=./drizzle.config.ts \ No newline at end of file + run: bun run ./scripts/migrate.ts \ No newline at end of file From 09e3a1090ccf67f2bd47a74a92fdba5403aac3ca Mon Sep 17 00:00:00 2001 From: Theodore Li Date: Tue, 26 May 2026 12:40:37 -0700 Subject: [PATCH 3/3] feat(hosted-keys): add Hunter.io and People Data Labs hosted key support --- apps/sim/.env.example | 9 +++++ .../settings/components/byok/byok.tsx | 16 +++++++++ apps/sim/blocks/blocks/hunter.ts | 1 + apps/sim/blocks/blocks/peopledatalabs.ts | 1 + apps/sim/lib/api/contracts/byok-keys.ts | 2 ++ apps/sim/tools/hunter/companies_find.ts | 13 +++++++ apps/sim/tools/hunter/discover.ts | 14 +++++++- apps/sim/tools/hunter/domain_search.ts | 28 ++++++++++++++- apps/sim/tools/hunter/email_count.ts | 14 +++++++- apps/sim/tools/hunter/email_finder.ts | 26 +++++++++++++- apps/sim/tools/hunter/email_verifier.ts | 24 ++++++++++++- apps/sim/tools/hunter/types.ts | 19 ++++++++++ apps/sim/tools/peopledatalabs/autocomplete.ts | 13 +++++++ .../peopledatalabs/bulk_company_enrich.ts | 28 ++++++++++++++- .../peopledatalabs/bulk_person_enrich.ts | 28 ++++++++++++++- .../sim/tools/peopledatalabs/company_clean.ts | 17 ++++++++- .../tools/peopledatalabs/company_enrich.ts | 24 ++++++++++++- .../tools/peopledatalabs/company_search.ts | 35 ++++++++++++++++++- .../tools/peopledatalabs/location_clean.ts | 17 ++++++++- .../sim/tools/peopledatalabs/person_enrich.ts | 24 ++++++++++++- .../tools/peopledatalabs/person_identify.ts | 28 ++++++++++++++- .../sim/tools/peopledatalabs/person_search.ts | 35 ++++++++++++++++++- apps/sim/tools/peopledatalabs/school_clean.ts | 17 ++++++++- apps/sim/tools/peopledatalabs/types.ts | 19 ++++++++++ apps/sim/tools/peopledatalabs/utils.ts | 14 ++++++++ apps/sim/tools/types.ts | 2 ++ 26 files changed, 453 insertions(+), 15 deletions(-) diff --git a/apps/sim/.env.example b/apps/sim/.env.example index f554797ea1e..f9fb463c3bc 100644 --- a/apps/sim/.env.example +++ b/apps/sim/.env.example @@ -38,6 +38,15 @@ API_ENCRYPTION_KEY=your_api_encryption_key # Use `openssl rand -hex 32` to gener # COHERE_API_KEY= # Cohere API key for the Knowledge block reranker (rerank-v4.0-pro/-fast, rerank-v3.5). Alternatively set COHERE_API_KEY_1/2/3 for rotation. # NEXT_PUBLIC_COHERE_CONFIGURED=true # Set when COHERE_API_KEY (or rotation keys) are pre-configured above. Hides the Cohere API Key field on the Knowledge block UI. +# Hosted tool API keys (Optional - lets Sim supply the key so users don't have to bring their own). +# Each provider reads `{PREFIX}_COUNT` then `{PREFIX}_1..N`, distributing requests round-robin across the keys. +# HUNTER_API_KEY_COUNT=2 # Number of Hunter.io keys for hosted Hunter blocks +# HUNTER_API_KEY_1= # Hunter.io API key #1 +# HUNTER_API_KEY_2= # Hunter.io API key #2 +# PEOPLEDATALABS_API_KEY_COUNT=2 # Number of People Data Labs keys for hosted PDL blocks +# PEOPLEDATALABS_API_KEY_1= # People Data Labs API key #1 +# PEOPLEDATALABS_API_KEY_2= # People Data Labs API key #2 + # Admin API (Optional - for self-hosted GitOps) # ADMIN_API_KEY= # Use `openssl rand -hex 32` to generate. Enables admin API for workflow export/import. # Usage: curl -H "x-admin-key: your_key" https://your-instance/api/v1/admin/workspaces diff --git a/apps/sim/app/workspace/[workspaceId]/settings/components/byok/byok.tsx b/apps/sim/app/workspace/[workspaceId]/settings/components/byok/byok.tsx index 306b62850cb..b4b28892c23 100644 --- a/apps/sim/app/workspace/[workspaceId]/settings/components/byok/byok.tsx +++ b/apps/sim/app/workspace/[workspaceId]/settings/components/byok/byok.tsx @@ -23,11 +23,13 @@ import { FireworksIcon, GeminiIcon, GoogleIcon, + HunterIOIcon, JinaAIIcon, LinkupIcon, MistralIcon, OpenAIIcon, ParallelIcon, + PeopleDataLabsIcon, PerplexityIcon, SerperIcon, } from '@/components/icons' @@ -148,6 +150,20 @@ const PROVIDERS: { description: 'Brand assets, logos, colors, and company info', placeholder: 'Enter your Brandfetch API key', }, + { + id: 'hunter', + name: 'Hunter', + icon: HunterIOIcon, + description: 'Email finder, verification, and domain search', + placeholder: 'Enter your Hunter.io API key', + }, + { + id: 'peopledatalabs', + name: 'People Data Labs', + icon: PeopleDataLabsIcon, + description: 'Person and company enrichment, search, and identity', + placeholder: 'Enter your People Data Labs API key', + }, ] export function BYOK() { diff --git a/apps/sim/blocks/blocks/hunter.ts b/apps/sim/blocks/blocks/hunter.ts index 4c26bb85d43..1cd983c2eca 100644 --- a/apps/sim/blocks/blocks/hunter.ts +++ b/apps/sim/blocks/blocks/hunter.ts @@ -256,6 +256,7 @@ Return ONLY the search query text - no explanations.`, required: true, placeholder: 'Enter your Hunter.io API key', password: true, + hideWhenHosted: true, }, ], tools: { diff --git a/apps/sim/blocks/blocks/peopledatalabs.ts b/apps/sim/blocks/blocks/peopledatalabs.ts index 2578574993e..1689fbb4acb 100644 --- a/apps/sim/blocks/blocks/peopledatalabs.ts +++ b/apps/sim/blocks/blocks/peopledatalabs.ts @@ -397,6 +397,7 @@ export const PeopleDataLabsBlock: BlockConfig = { placeholder: 'Enter your People Data Labs API key', password: true, required: true, + hideWhenHosted: true, }, ], diff --git a/apps/sim/lib/api/contracts/byok-keys.ts b/apps/sim/lib/api/contracts/byok-keys.ts index d427e506f32..0370b5fb6b2 100644 --- a/apps/sim/lib/api/contracts/byok-keys.ts +++ b/apps/sim/lib/api/contracts/byok-keys.ts @@ -17,6 +17,8 @@ export const byokProviderIdSchema = z.enum([ 'parallel_ai', 'brandfetch', 'cohere', + 'hunter', + 'peopledatalabs', ]) export const byokKeySchema = z.object({ diff --git a/apps/sim/tools/hunter/companies_find.ts b/apps/sim/tools/hunter/companies_find.ts index 4b158a91f3a..b92a59b3b1f 100644 --- a/apps/sim/tools/hunter/companies_find.ts +++ b/apps/sim/tools/hunter/companies_find.ts @@ -1,4 +1,5 @@ import type { HunterEnrichmentParams, HunterEnrichmentResponse } from '@/tools/hunter/types' +import { HUNTER_API_KEY_PREFIX } from '@/tools/hunter/types' import type { ToolConfig } from '@/tools/types' export const companiesFindTool: ToolConfig = { @@ -7,6 +8,18 @@ export const companiesFindTool: ToolConfig = { @@ -8,6 +8,18 @@ export const discoverTool: ToolConfig = { @@ -12,6 +16,28 @@ export const domainSearchTool: ToolConfig { + const emails = output.emails + if (!Array.isArray(emails)) { + throw new Error('Hunter domain search response missing emails, cannot determine cost') + } + // Hunter counts one search credit only when a call returns at least one result. + const cost = emails.length > 0 ? HUNTER_SEARCH_CREDIT_USD : 0 + return { cost, metadata: { credits: cost > 0 ? 1 : 0, emails: emails.length } } + }, + }, + rateLimit: { + mode: 'per_request', + requestsPerMinute: 60, + }, + }, + params: { domain: { type: 'string', diff --git a/apps/sim/tools/hunter/email_count.ts b/apps/sim/tools/hunter/email_count.ts index 021d290d4e8..25022267074 100644 --- a/apps/sim/tools/hunter/email_count.ts +++ b/apps/sim/tools/hunter/email_count.ts @@ -1,5 +1,5 @@ import type { HunterEmailCountParams, HunterEmailCountResponse } from '@/tools/hunter/types' -import { DEPARTMENT_OUTPUT, SENIORITY_OUTPUT } from '@/tools/hunter/types' +import { DEPARTMENT_OUTPUT, HUNTER_API_KEY_PREFIX, SENIORITY_OUTPUT } from '@/tools/hunter/types' import type { ToolConfig } from '@/tools/types' export const emailCountTool: ToolConfig = { @@ -8,6 +8,18 @@ export const emailCountTool: ToolConfig = { @@ -9,6 +14,25 @@ export const emailFinderTool: ToolConfig { + // Hunter counts one search credit only when an email is found. + const found = typeof output.email === 'string' && output.email.length > 0 + const cost = found ? HUNTER_SEARCH_CREDIT_USD : 0 + return { cost, metadata: { credits: found ? 1 : 0 } } + }, + }, + rateLimit: { + mode: 'per_request', + requestsPerMinute: 60, + }, + }, + params: { domain: { type: 'string', diff --git a/apps/sim/tools/hunter/email_verifier.ts b/apps/sim/tools/hunter/email_verifier.ts index 14c6efe43c7..c988bab6d2b 100644 --- a/apps/sim/tools/hunter/email_verifier.ts +++ b/apps/sim/tools/hunter/email_verifier.ts @@ -1,5 +1,9 @@ import type { HunterEmailVerifierParams, HunterEmailVerifierResponse } from '@/tools/hunter/types' -import { SOURCES_OUTPUT } from '@/tools/hunter/types' +import { + HUNTER_API_KEY_PREFIX, + HUNTER_VERIFICATION_CREDIT_USD, + SOURCES_OUTPUT, +} from '@/tools/hunter/types' import type { ToolConfig } from '@/tools/types' export const emailVerifierTool: ToolConfig = @@ -10,6 +14,24 @@ export const emailVerifierTool: ToolConfig ({ + cost: HUNTER_VERIFICATION_CREDIT_USD, + metadata: { verifications: 1 }, + }), + }, + rateLimit: { + mode: 'per_request', + requestsPerMinute: 60, + }, + }, + params: { email: { type: 'string', diff --git a/apps/sim/tools/hunter/types.ts b/apps/sim/tools/hunter/types.ts index 32c0177f8af..b77c1162f79 100644 --- a/apps/sim/tools/hunter/types.ts +++ b/apps/sim/tools/hunter/types.ts @@ -1,6 +1,25 @@ // Common types for Hunter.io tools import type { OutputProperty, ToolResponse } from '@/tools/types' +/** + * Env var prefix for Sim-hosted Hunter.io keys. + * Resolved at runtime as `HUNTER_API_KEY_COUNT` + `HUNTER_API_KEY_1..N`. + */ +export const HUNTER_API_KEY_PREFIX = 'HUNTER_API_KEY' + +/** + * Dollar cost per Hunter.io credit when billing hosted-key usage. + * + * Hunter does not report per-call credit consumption in its responses, so cost is + * derived from the response: a "search" credit is consumed only when a call returns + * at least one result; a verification consumes half a credit. + * + * Estimate based on the Growth plan ($149/mo for 10,000 credits ≈ $0.015/credit) — + * see https://hunter.io/pricing. Tune if Sim's plan rate changes. + */ +export const HUNTER_SEARCH_CREDIT_USD = 0.015 +export const HUNTER_VERIFICATION_CREDIT_USD = 0.0075 + /** * Shared output property definitions for Hunter.io API responses. * These are reusable across all Hunter tools to ensure consistency. diff --git a/apps/sim/tools/peopledatalabs/autocomplete.ts b/apps/sim/tools/peopledatalabs/autocomplete.ts index 588605f7a59..9353c3aa143 100644 --- a/apps/sim/tools/peopledatalabs/autocomplete.ts +++ b/apps/sim/tools/peopledatalabs/autocomplete.ts @@ -1,4 +1,5 @@ import type { PdlAutocompleteParams, PdlAutocompleteResponse } from '@/tools/peopledatalabs/types' +import { PEOPLEDATALABS_API_KEY_PREFIX } from '@/tools/peopledatalabs/types' import { buildQueryString } from '@/tools/peopledatalabs/utils' import type { OutputProperty, ToolConfig } from '@/tools/types' @@ -19,6 +20,18 @@ export const autocompleteTool: ToolConfig { + const matched = countBulkMatched(output) + return { cost: matched * PDL_CREDIT_USD, metadata: { credits: matched } } + }, + }, + rateLimit: { + mode: 'custom', + requestsPerMinute: 10, + dimensions: [ + { + name: 'credits', + limitPerMinute: 600, + extractUsage: (_params, response) => countBulkMatched(response), + }, + ], + }, + }, + params: { apiKey: { type: 'string', diff --git a/apps/sim/tools/peopledatalabs/bulk_person_enrich.ts b/apps/sim/tools/peopledatalabs/bulk_person_enrich.ts index 8df13c55e24..a993a8e1e22 100644 --- a/apps/sim/tools/peopledatalabs/bulk_person_enrich.ts +++ b/apps/sim/tools/peopledatalabs/bulk_person_enrich.ts @@ -3,7 +3,8 @@ import type { PdlBulkPersonEnrichResponse, PdlBulkPersonResultItem, } from '@/tools/peopledatalabs/types' -import { projectPerson } from '@/tools/peopledatalabs/utils' +import { PDL_CREDIT_USD, PEOPLEDATALABS_API_KEY_PREFIX } from '@/tools/peopledatalabs/types' +import { countBulkMatched, projectPerson } from '@/tools/peopledatalabs/utils' import type { OutputProperty, ToolConfig } from '@/tools/types' const BULK_PERSON_RESULT_PROPERTIES = { @@ -32,6 +33,31 @@ export const bulkPersonEnrichTool: ToolConfig< 'Enrich up to 100 person records in a single call. Provide a JSON array of request objects, each with a `params` object (and optional `metadata` echoed back). Reference: https://docs.peopledatalabs.com/docs/bulk-person-enrichment-api', version: '1.0.0', + hosting: { + envKeyPrefix: PEOPLEDATALABS_API_KEY_PREFIX, + apiKeyParam: 'apiKey', + byokProviderId: 'peopledatalabs', + pricing: { + type: 'custom', + // PDL charges 1 credit per matched record; unmatched records in the batch are free. + getCost: (_params, output) => { + const matched = countBulkMatched(output) + return { cost: matched * PDL_CREDIT_USD, metadata: { credits: matched } } + }, + }, + rateLimit: { + mode: 'custom', + requestsPerMinute: 10, + dimensions: [ + { + name: 'credits', + limitPerMinute: 600, + extractUsage: (_params, response) => countBulkMatched(response), + }, + ], + }, + }, + params: { apiKey: { type: 'string', diff --git a/apps/sim/tools/peopledatalabs/company_clean.ts b/apps/sim/tools/peopledatalabs/company_clean.ts index 65aaff4b87f..67b34ab2492 100644 --- a/apps/sim/tools/peopledatalabs/company_clean.ts +++ b/apps/sim/tools/peopledatalabs/company_clean.ts @@ -1,5 +1,8 @@ import type { PdlCleanCompanyParams, PdlCleanCompanyResponse } from '@/tools/peopledatalabs/types' -import { PDL_COMPANY_OUTPUT_PROPERTIES } from '@/tools/peopledatalabs/types' +import { + PDL_COMPANY_OUTPUT_PROPERTIES, + PEOPLEDATALABS_API_KEY_PREFIX, +} from '@/tools/peopledatalabs/types' import { projectCompany } from '@/tools/peopledatalabs/utils' import type { ToolConfig } from '@/tools/types' @@ -10,6 +13,18 @@ export const cleanCompanyTool: ToolConfig { + const cost = output.matched === true ? PDL_CREDIT_USD : 0 + return { cost, metadata: { credits: output.matched === true ? 1 : 0 } } + }, + }, + rateLimit: { + mode: 'per_request', + requestsPerMinute: 60, + }, + }, + params: { apiKey: { type: 'string', diff --git a/apps/sim/tools/peopledatalabs/company_search.ts b/apps/sim/tools/peopledatalabs/company_search.ts index 2c71d66aa41..9027045ab52 100644 --- a/apps/sim/tools/peopledatalabs/company_search.ts +++ b/apps/sim/tools/peopledatalabs/company_search.ts @@ -1,5 +1,9 @@ import type { PdlCompanySearchParams, PdlCompanySearchResponse } from '@/tools/peopledatalabs/types' -import { PDL_COMPANY_OUTPUT_PROPERTIES } from '@/tools/peopledatalabs/types' +import { + PDL_COMPANY_OUTPUT_PROPERTIES, + PDL_CREDIT_USD, + PEOPLEDATALABS_API_KEY_PREFIX, +} from '@/tools/peopledatalabs/types' import { projectCompany } from '@/tools/peopledatalabs/utils' import type { ToolConfig } from '@/tools/types' @@ -10,6 +14,35 @@ export const companySearchTool: ToolConfig { + const results = output.results + if (!Array.isArray(results)) { + throw new Error('PDL company search response missing results, cannot determine cost') + } + return { cost: results.length * PDL_CREDIT_USD, metadata: { credits: results.length } } + }, + }, + rateLimit: { + mode: 'custom', + requestsPerMinute: 30, + dimensions: [ + { + name: 'credits', + limitPerMinute: 600, + extractUsage: (_params, response) => + Array.isArray(response.results) ? response.results.length : 0, + }, + ], + }, + }, + params: { apiKey: { type: 'string', diff --git a/apps/sim/tools/peopledatalabs/location_clean.ts b/apps/sim/tools/peopledatalabs/location_clean.ts index e08e7a6f5aa..4222d3345f5 100644 --- a/apps/sim/tools/peopledatalabs/location_clean.ts +++ b/apps/sim/tools/peopledatalabs/location_clean.ts @@ -1,5 +1,8 @@ import type { PdlCleanLocationParams, PdlCleanLocationResponse } from '@/tools/peopledatalabs/types' -import { PDL_LOCATION_OUTPUT_PROPERTIES } from '@/tools/peopledatalabs/types' +import { + PDL_LOCATION_OUTPUT_PROPERTIES, + PEOPLEDATALABS_API_KEY_PREFIX, +} from '@/tools/peopledatalabs/types' import { projectLocation } from '@/tools/peopledatalabs/utils' import type { ToolConfig } from '@/tools/types' @@ -10,6 +13,18 @@ export const cleanLocationTool: ToolConfig { + const cost = output.matched === true ? PDL_CREDIT_USD : 0 + return { cost, metadata: { credits: output.matched === true ? 1 : 0 } } + }, + }, + rateLimit: { + mode: 'per_request', + requestsPerMinute: 60, + }, + }, + params: { apiKey: { type: 'string', diff --git a/apps/sim/tools/peopledatalabs/person_identify.ts b/apps/sim/tools/peopledatalabs/person_identify.ts index d68f74e3c24..7a16aa1fcb2 100644 --- a/apps/sim/tools/peopledatalabs/person_identify.ts +++ b/apps/sim/tools/peopledatalabs/person_identify.ts @@ -2,7 +2,11 @@ import type { PdlPersonIdentifyParams, PdlPersonIdentifyResponse, } from '@/tools/peopledatalabs/types' -import { PDL_PERSON_OUTPUT_PROPERTIES } from '@/tools/peopledatalabs/types' +import { + PDL_CREDIT_USD, + PDL_PERSON_OUTPUT_PROPERTIES, + PEOPLEDATALABS_API_KEY_PREFIX, +} from '@/tools/peopledatalabs/types' import { buildQueryString, projectPerson } from '@/tools/peopledatalabs/utils' import type { OutputProperty, ToolConfig } from '@/tools/types' @@ -28,6 +32,28 @@ export const personIdentifyTool: ToolConfig { + const matches = output.matches + if (!Array.isArray(matches)) { + throw new Error('PDL identify response missing matches, cannot determine cost') + } + const cost = matches.length > 0 ? PDL_CREDIT_USD : 0 + return { cost, metadata: { credits: matches.length > 0 ? 1 : 0 } } + }, + }, + rateLimit: { + mode: 'per_request', + requestsPerMinute: 60, + }, + }, + params: { apiKey: { type: 'string', diff --git a/apps/sim/tools/peopledatalabs/person_search.ts b/apps/sim/tools/peopledatalabs/person_search.ts index 4efb94edd8d..17adeb1721b 100644 --- a/apps/sim/tools/peopledatalabs/person_search.ts +++ b/apps/sim/tools/peopledatalabs/person_search.ts @@ -1,5 +1,9 @@ import type { PdlPersonSearchParams, PdlPersonSearchResponse } from '@/tools/peopledatalabs/types' -import { PDL_PERSON_OUTPUT_PROPERTIES } from '@/tools/peopledatalabs/types' +import { + PDL_CREDIT_USD, + PDL_PERSON_OUTPUT_PROPERTIES, + PEOPLEDATALABS_API_KEY_PREFIX, +} from '@/tools/peopledatalabs/types' import { projectPerson } from '@/tools/peopledatalabs/utils' import type { ToolConfig } from '@/tools/types' @@ -10,6 +14,35 @@ export const personSearchTool: ToolConfig { + const results = output.results + if (!Array.isArray(results)) { + throw new Error('PDL person search response missing results, cannot determine cost') + } + return { cost: results.length * PDL_CREDIT_USD, metadata: { credits: results.length } } + }, + }, + rateLimit: { + mode: 'custom', + requestsPerMinute: 30, + dimensions: [ + { + name: 'credits', + limitPerMinute: 600, + extractUsage: (_params, response) => + Array.isArray(response.results) ? response.results.length : 0, + }, + ], + }, + }, + params: { apiKey: { type: 'string', diff --git a/apps/sim/tools/peopledatalabs/school_clean.ts b/apps/sim/tools/peopledatalabs/school_clean.ts index 5ae7cc3d504..e890867a5e9 100644 --- a/apps/sim/tools/peopledatalabs/school_clean.ts +++ b/apps/sim/tools/peopledatalabs/school_clean.ts @@ -1,5 +1,8 @@ import type { PdlCleanSchoolParams, PdlCleanSchoolResponse } from '@/tools/peopledatalabs/types' -import { PDL_SCHOOL_OUTPUT_PROPERTIES } from '@/tools/peopledatalabs/types' +import { + PDL_SCHOOL_OUTPUT_PROPERTIES, + PEOPLEDATALABS_API_KEY_PREFIX, +} from '@/tools/peopledatalabs/types' import { projectSchool } from '@/tools/peopledatalabs/utils' import type { ToolConfig } from '@/tools/types' @@ -10,6 +13,18 @@ export const cleanSchoolTool: ToolConfig): number { + const results = output.results + if (!Array.isArray(results)) return 0 + return results.reduce((count, item) => { + const matched = (item as { matched?: unknown }).matched + return matched === true ? count + 1 : count + }, 0) +} + /** * Build a query string from non-empty params. */ diff --git a/apps/sim/tools/types.ts b/apps/sim/tools/types.ts index 5cd428c941e..f45c0a01903 100644 --- a/apps/sim/tools/types.ts +++ b/apps/sim/tools/types.ts @@ -18,6 +18,8 @@ export type BYOKProviderId = | 'brandfetch' | 'parallel_ai' | 'cohere' + | 'hunter' + | 'peopledatalabs' export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD'