feat(hosted-keys): add Hunter.io and People Data Labs hosted key support#4742
feat(hosted-keys): add Hunter.io and People Data Labs hosted key support#4742TheodoreSpeaks wants to merge 4 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR SummaryMedium Risk Overview Hunter — all six tools get Product surface — Reviewed by Cursor Bugbot for commit ecd9ef0. Bugbot is set up for automated code reviews on this repo. Configure here. |
Greptile SummaryThis PR adds Sim-hosted API key support for all Hunter.io and People Data Labs tools, registering both as BYOK providers and wiring per-tool pricing and rate-limit configs that meter usage when Sim supplies the key.
Confidence Score: 4/5The core hosted-key plumbing is consistent with existing providers, BYOK contract and type union are correctly extended, and the pricing logic matches documented Hunter/PDL billing models. The getCost/extractUsage inconsistency is safe today but fragile if transformResponse is ever refactored. The implementation is well-structured and follows established patterns. The getCost functions that throw on missing array fields (person_search, company_search, domain_search, person_identify) are inconsistent with their paired extractUsage lambdas that return 0 gracefully — if output fields are ever absent, a successful API call would surface an error to the user. The bulk enrich tools handle this correctly via countBulkMatched. apps/sim/tools/peopledatalabs/person_search.ts, company_search.ts, person_identify.ts, and apps/sim/tools/hunter/domain_search.ts — the inconsistency between getCost throwing and extractUsage returning 0 is worth aligning before this pattern spreads to more tools. Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant ToolExecutor as Tool Executor (index.ts)
participant HKRL as HostedKeyRateLimiter
participant API as Hunter.io / PDL API
User->>ToolExecutor: Execute tool (no BYOK key)
ToolExecutor->>HKRL: acquireKey(provider, envKeyPrefix, config, workspaceId)
HKRL-->>ToolExecutor: key (round-robin selected)
ToolExecutor->>API: HTTP request (hosted key injected)
API-->>ToolExecutor: Response
ToolExecutor->>ToolExecutor: transformResponse → output
ToolExecutor->>ToolExecutor: applyHostedKeyCostToResult()
ToolExecutor->>ToolExecutor: pricing.getCost(params, output) → cost
ToolExecutor->>HKRL: reportUsage (custom dimensions only)
ToolExecutor-->>User: output + cost metadata
Reviews (1): Last reviewed commit: "Merge branch 'staging' into feat/hosted-..." | Re-trigger Greptile |
| if (!Array.isArray(results)) { | ||
| throw new Error('PDL person search response missing results, cannot determine cost') | ||
| } |
There was a problem hiding this comment.
Asymmetric error handling between
getCost and extractUsage
getCost throws when results is not an array, but the paired extractUsage lambda in the same rateLimit.dimensions block returns 0 gracefully for the exact same condition. If output.results were ever missing (e.g., after a future transformResponse refactor), extractUsage would silently record 0 credits while getCost would throw — causing the tool to return an error to the caller even though the upstream API call already succeeded. The same inconsistency appears in company_search.ts and, in slightly different form, in domain_search.ts (emails) and person_identify.ts (matches). countBulkMatched in the bulk tools avoids this by returning 0 rather than throwing.
Summary
Type of Change
Testing
Tested manually. `bun run lint`, `bun run check:api-validation:strict`, `tsc --noEmit`, and the 92 tool/rate-limiter tests all pass.
Checklist