diff --git a/extensions/copilot/src/extension/conversation/vscode-node/languageModelAccess.ts b/extensions/copilot/src/extension/conversation/vscode-node/languageModelAccess.ts index 1092915ca08..d9d470af509 100644 --- a/extensions/copilot/src/extension/conversation/vscode-node/languageModelAccess.ts +++ b/extensions/copilot/src/extension/conversation/vscode-node/languageModelAccess.ts @@ -424,16 +424,6 @@ export class LanguageModelAccess extends Disposable implements IExtensionContrib // Only publish the alias as an entry under the `copilot` vendor // when the resolved endpoint is itself a copilot-provider endpoint. - // - // Publishing a BYOK-backed alias here would let any extension - // resolve `vscode.lm.selectChatModels({ vendor: 'copilot', id: - // 'copilot-utility[-small]' })` and proxy requests through the - // user's BYOK endpoint without going through that provider's - // authorization flow. `isUserSelectable: false` does not prevent - // the explicit-id selector from matching the entry. Internal - // utility callers do not depend on the alias being published — - // they go through `IEndpointProvider.getChatEndpoint(family)`, - // which already honors the override. if (!(endpoint instanceof CopilotChatEndpoint)) { this._logService.trace(`[LanguageModelAccess] Not publishing alias '${family}' for non-copilot endpoint '${endpoint.model}' (BYOK override) to avoid bypassing the underlying provider's authorization.`); continue; diff --git a/extensions/copilot/src/extension/prompt/vscode-node/endpointProviderImpl.ts b/extensions/copilot/src/extension/prompt/vscode-node/endpointProviderImpl.ts index c7c6661e11e..331cc8716b4 100644 --- a/extensions/copilot/src/extension/prompt/vscode-node/endpointProviderImpl.ts +++ b/extensions/copilot/src/extension/prompt/vscode-node/endpointProviderImpl.ts @@ -141,11 +141,7 @@ export class ProductionEndpointProvider extends Disposable implements IEndpointP * selection for each family lives in the corresponding resolver * class so callers don't need to know which CAPI family backs each * purpose. - * - * If the user has configured a model override for the family via the - * `chat.utilityModel` / `chat.utilitySmallModel` settings, this method - * attempts to resolve that model first and falls back to the default - * CAPI-driven resolution if the override cannot be located. + */ private async _resolveUtilityFamily(family: ChatEndpointFamily): Promise { const override = await this._resolveUtilityOverride(family); @@ -163,9 +159,7 @@ export class ProductionEndpointProvider extends Disposable implements IEndpointP /** * Resolves the user's `chat.utilityModel` / `chat.utilitySmallModel` - * override (if any) to a concrete chat endpoint. The stored value is - * encoded as `${vendor}/${id}` to be stable across UI changes and - * directly compatible with `vscode.lm.selectChatModels({ vendor, id })`. + * override (if any) to a concrete chat endpoint. * Returns `undefined` if no override is configured, if the value is * malformed, if no matching model is currently available, or if the * lookup throws. @@ -180,9 +174,6 @@ export class ProductionEndpointProvider extends Disposable implements IEndpointP return undefined; } - // `getNonExtensionConfig` only narrows the type at compile - // time; at runtime the value can be anything the user wrote into - // settings.json. Treat any non-string value as "no override". const raw = this._configService.getNonExtensionConfig(configKey); if (typeof raw !== 'string' || raw.length === 0) { if (raw !== undefined && typeof raw !== 'string') { @@ -251,16 +242,6 @@ export class ProductionEndpointProvider extends Disposable implements IEndpointP return this._instantiationService.createInstance(ExtensionContributedChatEndpoint, model); } - /** - * Emits a telemetry event the first time (per family) we successfully - * apply a utility-model override. Resolution runs on every utility-alias - * publish, so unguarded emission would be very noisy; we dedupe so we - * emit at most once per family until the override is changed (which - * clears the cache via {@link _lastOverrideTelemetryFingerprint}). - * Failed/fallback resolutions are intentionally not reported. The event - * carries no vendor or model identifiers — those can be user-provided - * values for BYOK/custom endpoint providers. - */ private _reportOverrideAppliedTelemetry(family: ChatEndpointFamily): void { if (this._lastOverrideTelemetryFingerprint.has(family)) { return; diff --git a/src/vs/workbench/contrib/chat/browser/defaultModelContribution.ts b/src/vs/workbench/contrib/chat/browser/defaultModelContribution.ts index 153fad8e204..3b6942cda2f 100644 --- a/src/vs/workbench/contrib/chat/browser/defaultModelContribution.ts +++ b/src/vs/workbench/contrib/chat/browser/defaultModelContribution.ts @@ -40,21 +40,16 @@ export interface DefaultModelContributionOptions { * When `true`, eagerly call `selectLanguageModels({})` at construction * time and on `onDidChangeLanguageModelVendors` to force every registered * provider extension to resolve its models. This ensures models from - * providers that no other consumer has touched yet (e.g. BYOK Anthropic - * / OpenAI) surface in the picker — at the cost of activating those - * provider extensions. + * providers that no other consumer has touched yet (e.g. BYOK) surface in + * the picker at the cost of activating those provider extensions. * * Defaults to `false` so contributions that run during startup - * (`BlockRestore`) don't pay that activation cost. Contributions that - * register at later phases (e.g. `Eventually`) can opt in. + * (`BlockRestore`) don't pay that activation cost. */ readonly eagerVendorResolution?: boolean; /** * Optional override for the label of the default ("empty") enum entry. - * When omitted, defaults to `"Auto (Vendor Default)"`. Provide a - * setting-specific copy when the empty value does not represent a - * vendor-default (e.g. `chat.utilityModel` falls back to the built-in - * utility family default, not a vendor default). + * When omitted, defaults to `"Auto (Vendor Default)"`. */ readonly defaultEntryLabel?: string; /** @@ -68,9 +63,6 @@ export interface DefaultModelContributionOptions { * Creates the initial static arrays used by configuration registration code. * The returned arrays are mutated in-place by {@link DefaultModelContribution}. * - * `defaultEntryLabel` / `defaultEntryDescription` override the copy used for - * the empty/default enum entry. Pass setting-specific copy when the empty - * value does not represent a vendor-default. */ export function createDefaultModelArrays(defaultEntryLabel?: string, defaultEntryDescription?: string): DefaultModelArrays { return { @@ -95,10 +87,7 @@ export abstract class DefaultModelContribution extends Disposable { super(); this._register(_languageModelsService.onDidChangeLanguageModels(() => this._updateModelValues())); if (_options.eagerVendorResolution) { - // New vendors (e.g. BYOK Anthropic) may register after this contribution - // has already started. Re-trigger resolution so their models surface in - // the picker too — `selectLanguageModels({})` only resolves vendors that - // were registered at call time. + // New vendors (e.g. BYOK) may register after this contribution has already started. this._register(_languageModelsService.onDidChangeLanguageModelVendors(() => this._resolveAllVendors())); } this._updateModelValues(); @@ -108,13 +97,6 @@ export abstract class DefaultModelContribution extends Disposable { } private _resolveAllVendors(): void { - // Trigger resolution of every registered vendor so models from providers that - // haven't yet been touched by another consumer (e.g. BYOK Anthropic / OpenAI) - // also surface in the picker. Each vendor's resolution will fire - // `onDidChangeLanguageModels`, which re-runs `_updateModelValues` above. - // We additionally re-run `_updateModelValues` once everything resolves so that - // providers which add no new models (and therefore don't fire the change event) - // still get reflected in the picker. const vendors = this._languageModelsService.getVendors().map(v => v.vendor); this._logService.trace(`${this._options.logPrefix} Resolving all vendors: [${vendors.join(', ')}]`); this._languageModelsService.selectLanguageModels({}).then(