Skip to content
This repository was archived by the owner on May 20, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from 1 commit
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
17 changes: 17 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1797,6 +1797,23 @@
]
}
},
{
"vendor": "perplexity",
"displayName": "Perplexity",
"configuration": {
"properties": {
"apiKey": {
"type": "string",
"secret": true,
"description": "API key for Perplexity",
"title": "API Key"
}
},
"required": [
"apiKey"
]
}
},
{
"vendor": "openai",
"displayName": "OpenAI",
Expand Down
2 changes: 2 additions & 0 deletions src/extension/byok/vscode-node/byokContribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { GeminiNativeBYOKLMProvider } from './geminiNativeProvider';
import { OllamaLMProvider } from './ollamaProvider';
import { OAIBYOKLMProvider } from './openAIProvider';
import { OpenRouterLMProvider } from './openRouterProvider';
import { PerplexityLMProvider } from './perplexityProvider';
import { XAIBYOKLMProvider } from './xAIProvider';

export class BYOKContrib extends Disposable implements IExtensionContribution {
Expand Down Expand Up @@ -59,6 +60,7 @@ export class BYOKContrib extends Disposable implements IExtensionContribution {
this._providers.set(XAIBYOKLMProvider.providerName.toLowerCase(), instantiationService.createInstance(XAIBYOKLMProvider, knownModels[XAIBYOKLMProvider.providerName], this._byokStorageService));
this._providers.set(OAIBYOKLMProvider.providerName.toLowerCase(), instantiationService.createInstance(OAIBYOKLMProvider, knownModels[OAIBYOKLMProvider.providerName], this._byokStorageService));
this._providers.set(OpenRouterLMProvider.providerName.toLowerCase(), instantiationService.createInstance(OpenRouterLMProvider, this._byokStorageService));
this._providers.set(PerplexityLMProvider.providerName.toLowerCase(), instantiationService.createInstance(PerplexityLMProvider, knownModels[PerplexityLMProvider.providerName], this._byokStorageService));
this._providers.set(AzureBYOKModelProvider.providerName.toLowerCase(), instantiationService.createInstance(AzureBYOKModelProvider, this._byokStorageService));
this._providers.set(CustomOAIBYOKModelProvider.providerName.toLowerCase(), instantiationService.createInstance(CustomOAIBYOKModelProvider, this._byokStorageService));

Expand Down
116 changes: 116 additions & 0 deletions src/extension/byok/vscode-node/perplexityProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IConfigurationService } from '../../../platform/configuration/common/configurationService';
import { ILogService } from '../../../platform/log/common/logService';
import { IFetcherService } from '../../../platform/networking/common/fetcherService';
import { IExperimentationService } from '../../../platform/telemetry/common/nullExperimentationService';
import { IInstantiationService } from '../../../util/vs/platform/instantiation/common/instantiation';
import { packageJson } from '../../../platform/env/common/packagejson';
import { BYOKKnownModels, BYOKModelCapabilities } from '../common/byokProvider';
import { AbstractOpenAICompatibleLMProvider } from './abstractLanguageModelChatProvider';
import { IBYOKStorageService } from './byokStorageService';

// https://docs.perplexity.ai/models/model-cards
// Perplexity exposes an OpenAI-compatible chat completions API at https://api.perplexity.ai
// but does not provide a stable `/models` discovery endpoint. We ship a curated list.
const PERPLEXITY_INTEGRATION_HEADER = 'X-Pplx-Integration';

const PERPLEXITY_KNOWN_MODELS: BYOKKnownModels = {
'sonar-pro': {
name: 'Sonar Pro',
toolCalling: true,
vision: false,
maxInputTokens: 200000,
maxOutputTokens: 8000,
},
'sonar': {
name: 'Sonar',
toolCalling: true,
vision: false,
maxInputTokens: 128000,
maxOutputTokens: 8000,
},
'sonar-reasoning-pro': {
name: 'Sonar Reasoning Pro',
toolCalling: true,
vision: false,
maxInputTokens: 128000,
maxOutputTokens: 8000,
thinking: true,
},
'sonar-reasoning': {
name: 'Sonar Reasoning',
toolCalling: true,
vision: false,
maxInputTokens: 128000,
maxOutputTokens: 8000,
thinking: true,
},
};

export class PerplexityLMProvider extends AbstractOpenAICompatibleLMProvider {

public static readonly providerName = 'Perplexity';

constructor(
Comment on lines +61 to +65

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A new BYOK provider is introduced but there are no accompanying unit tests under src/extension/byok/vscode-node/test/ (other providers like Ollama/Gemini/Azure have coverage). Adding a Perplexity provider spec would help lock in: the curated model list shown in the picker and that X-Pplx-Integration is present in each model's requestHeaders.

Copilot uses AI. Check for mistakes.
knownModels: BYOKKnownModels | undefined,
byokStorageService: IBYOKStorageService,
@IFetcherService fetcherService: IFetcherService,
@ILogService logService: ILogService,
@IInstantiationService instantiationService: IInstantiationService,
@IConfigurationService configurationService: IConfigurationService,
@IExperimentationService expService: IExperimentationService
) {
super(
PerplexityLMProvider.providerName.toLowerCase(),
PerplexityLMProvider.providerName,
PerplexityLMProvider.mergeKnownModels(knownModels),
byokStorageService,
fetcherService,
logService,
instantiationService,
configurationService,
expService
);
}

private static mergeKnownModels(remote: BYOKKnownModels | undefined): BYOKKnownModels {
const integrationHeader = {
[PERPLEXITY_INTEGRATION_HEADER]: `vscode-copilot/${packageJson.version}`,
};
const merged: BYOKKnownModels = {};
for (const [id, caps] of Object.entries(PERPLEXITY_KNOWN_MODELS)) {
merged[id] = { ...caps, requestHeaders: { ...integrationHeader, ...(caps.requestHeaders ?? {}) } };
}
if (remote) {
for (const [id, caps] of Object.entries(remote)) {
merged[id] = { ...caps, requestHeaders: { ...integrationHeader, ...(caps.requestHeaders ?? {}) } };

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The merge order for requestHeaders allows an existing caps.requestHeaders entry to override X-Pplx-Integration, which can accidentally drop or change the attribution header. If the intent is to guarantee the header on every request, apply the integration header last (so it wins) when merging curated and remote model capabilities.

Suggested change
merged[id] = { ...caps, requestHeaders: { ...integrationHeader, ...(caps.requestHeaders ?? {}) } };
}
if (remote) {
for (const [id, caps] of Object.entries(remote)) {
merged[id] = { ...caps, requestHeaders: { ...integrationHeader, ...(caps.requestHeaders ?? {}) } };
merged[id] = { ...caps, requestHeaders: { ...(caps.requestHeaders ?? {}), ...integrationHeader } };
}
if (remote) {
for (const [id, caps] of Object.entries(remote)) {
merged[id] = { ...caps, requestHeaders: { ...(caps.requestHeaders ?? {}), ...integrationHeader } };

Copilot uses AI. Check for mistakes.
}
}
return merged;
}

protected getModelsBaseUrl(): string | undefined {
return 'https://api.perplexity.ai';

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getModelsBaseUrl() returns a base URL, which causes AbstractOpenAICompatibleLMProvider to always call ${baseUrl}/models for discovery. That contradicts the comment/PR description that Perplexity doesn't have a stable /models endpoint, and it also means the curated PERPLEXITY_KNOWN_MODELS list will never be shown unless the discovery call succeeds and returns those IDs. Consider overriding getAllModels (like CustomOAI does) to return the curated/merged known-model list with url set to the Perplexity base URL, optionally attempting discovery as a best-effort fallback rather than a hard dependency.

Suggested change
return 'https://api.perplexity.ai';
// Perplexity does not provide a stable /models discovery endpoint for this provider.
// Rely on the curated known-model list instead of enabling generic discovery.
return undefined;

Copilot uses AI. Check for mistakes.
}

protected override resolveModelCapabilities(modelData: unknown): BYOKModelCapabilities | undefined {
const data = modelData as { id?: string; name?: string };
if (!data?.id) {
return undefined;
}
// Sensible defaults for any model returned by /models that we don't already know about.
return {
name: data.name ?? data.id,
toolCalling: true,
vision: false,
maxInputTokens: 128000,
maxOutputTokens: 8000,
requestHeaders: {
[PERPLEXITY_INTEGRATION_HEADER]: `vscode-copilot/${packageJson.version}`,
},
};
}
}
Loading