Skip to content

feat: add Exa AI-powered search tool#19

Merged
askalf merged 1 commit into
askalf:masterfrom
tgonzalezc5:add-exa-search-adapter
May 2, 2026
Merged

feat: add Exa AI-powered search tool#19
askalf merged 1 commit into
askalf:masterfrom
tgonzalezc5:add-exa-search-adapter

Conversation

@tgonzalezc5
Copy link
Copy Markdown
Contributor

Summary

Adds Exa as a fifth search adapter, alongside DuckDuckGo, SearXNG, Brave, and Tavily. Exa is a neural-search API tuned for long, intent-rich queries — the shape the planner's sub-queries and the critic loop's gap-filling follow-ups tend to take.

  • New adapter ExaSearch in src/search/exa.ts (~50 lines, no new runtime deps; uses raw fetch matching the Tavily / Brave pattern)
  • Wired into resolveSearchAdapter in src/search.ts behind --search=exa and DEEPDIVE_EXA_KEY
  • Snippet cascade: highlights → text → summary → "" so the adapter degrades gracefully across content modes
  • Pure mapping function mapExaResults extracted for testability per the project's "pure decision functions" principle
  • Includes x-exa-integration: deepdive header so Exa can attribute usage from this integration
  • README adapter table + flag table + sovereignty paragraph updated; --help output and env var list updated; deepdive doctor picks up the new adapter automatically via resolveSearchAdapter

Usage

export DEEPDIVE_EXA_KEY=...
deepdive "how does claude's rate limiter work" --search=exa --deep --verbose --out=report.md

Files changed

  • src/search/exa.ts (new) — adapter + pure mapping function
  • src/search.ts — register exa case in resolveSearchAdapter
  • src/cli.ts — adapter list in --help, env var in usage footer
  • README.md — sovereignty paragraph, flag row, adapter row
  • test/exa-adapter.test.mjs (new) — 14 tests covering parsing, snippet fallback cascade, resolver wiring, request shape (headers, body, numResults cap), and HTTP error handling

Test plan

  • npm run typecheck — passes
  • npm run build — passes
  • npm test — 212/212 pass (14 new)
  • Snippet fallback verified across all four states (highlights / text / summary / none)
  • Adapter throws clearly when DEEPDIVE_EXA_KEY is unset
  • Request body verified to send x-api-key and x-exa-integration: deepdive headers
  • Live API smoke test against api.exa.ai (requires a key; tested locally on my end with deepdive "..." --search=exa --verbose, leaving this unchecked since CI won't have a key)

@askalf askalf merged commit bbecd3c into askalf:master May 2, 2026
5 checks passed
@askalf
Copy link
Copy Markdown
Owner

askalf commented May 2, 2026

Thanks for this PR, @tgonzalezc5 — genuinely high-quality contribution. The pure mapExaResults extraction, the snippet-cascade fallback, the typed response interface, and the integration-attribution header all show real care. Exa was on the wishlist; you put it in better than it would've shipped if I'd written it. Appreciate it 🙏

@askalf askalf mentioned this pull request May 2, 2026
5 tasks
askalf added a commit that referenced this pull request May 2, 2026
Co-authored-by: askalf <263217947+askalf@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants