microsoft / microsoft/vscode-websearchforcopilot
Support pluggable search engines — add Perplexity (direct or via LiteLLM-style proxy)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 65
- Forks
- 15
- PR merge metrics
- No merged PRs in 30d
Description
Summary
The extension currently hard-codes Tavily as the only web search backend. It would be great to support pluggable search engines — in particular Perplexity's Search API, which has a compatible results shape and is also available through OpenAI-compatible proxies (e.g. LiteLLM gateway at an https://<host>/v1/search/perplexity-search route).
Motivation
Corporate/offline-adjacent setups often already have a fronting gateway for LLM traffic (LiteLLM-style proxies exposing inference-api endpoints) that also proxies Perplexity search. Users in those environments cannot sign up for Tavily and thus the vscode-websearchforcopilot_webSearch LM tool and the @websearch participant are unusable today — TavilyEngine.search() calls vscode.authentication.getSession('tavily', ..., { createIfNone: true }), which blocks on a key they'll never have.
Current coupling points
src/search/webSearch.ts—TavilyEnginewith staticsearch()/extract()methods; API key passed in the POST body (api_key), which is Tavily-specific auth.src/search/webSearchTypes.ts— request/response types reference Tavily schemas.src/chatTool.tsx— callsTavilyEngine.search()directly.
Proposed shape (happy to send a PR)
- Introduce an
ISearchEngineinterface inwebSearchTypes.ts:interface ISearchEngine { search(query: string, opts?: { maxResults?: number; domains?: string[]; recency?: string }): Promise<IWebSearchResults>; extract?(urls: string[]): Promise<ITavilyExtractResponse>; // optional } - Refactor
TavilyEngineto implement it (no behavior change). - Add
PerplexityEnginetargetingPOST {baseUrl}/searchwith body{ query, max_results, search_recency_filter, search_domain_filter }and Bearer-token auth (works against bothapi.perplexity.aiand LiteLLM-style proxies at/v1/search/perplexity-search). - Settings:
websearch.engine:"tavily" | "perplexity"(default"tavily"— fully backwards compatible)websearch.perplexity.baseUrl(defaulthttps://api.perplexity.ai)- Reuse the existing
ApiKeySecretStoragepattern with a second auth provider id (e.g.perplexity), with env-var fallback.
- Perplexity response (
results[].{title,url,snippet,...}) maps 1:1 onto the existingIWebSearchResults(noanswerfield — that's fine, it's optional and the extension already tolerates its absence when falling back to direct snippets).
The response-shape compatibility means the change is ~2 new files + small edits to chatTool.tsx / chatParticipant.ts / package.json.
Questions for maintainers
- Are you open to a PR along these lines?
- Preference on config shape: single
engineenum switch, or per-tool overrides? - Should the Perplexity client's
max_results/recency/domain_filterbe exposed as tool parameters for the LM to control, or kept as settings only?
I'm willing to implement and test this end-to-end (including against a LiteLLM-proxied Perplexity route).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read src/search/webSearch.ts, src/search/webSearchTypes.ts, and src/chatTool.tsx first; trace how the current Tavily engine is selected and called. Then check src/chatParticipant.ts and package.json for integration points, and verify that both configured backends preserve the existing search result behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript, vscode
- Domain
- api, search, tooling
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100