diff --git a/.github/instructions/azure-provider-settings.instructions.md b/.github/instructions/azure-provider-settings.instructions.md new file mode 100644 index 0000000000..3262d889c5 --- /dev/null +++ b/.github/instructions/azure-provider-settings.instructions.md @@ -0,0 +1,194 @@ +--- +applyTo: '**/byok/**' +description: Azure provider settings format and configuration guidelines +--- + +# Azure Provider Settings Configuration + +Guidelines for configuring Azure OpenAI models in the BYOK (Bring Your Own Key) system using the `chat.azureModels` VS Code setting. + +## Settings Format + +The `chat.azureModels` setting accepts a record of model configurations where each key is a unique model identifier and the value is a model configuration object. + +### Model Configuration Schema + +```typescript +{ + "chat.azureModels": { + "[modelId]": { + "name": string, // Display name for the model + "url": string, // Azure endpoint URL (base URL without API path) + "deploymentType"?: "completions" | "responses", // API type (optional, defaults to "completions") + "deploymentName"?: string, // Azure deployment name (optional, defaults to modelId) + "apiVersion"?: string, // Azure API version (optional, default: "2025-01-01-preview") + "maxInputTokens": number, // Maximum input context window size + "maxOutputTokens": number, // Maximum output tokens per response + "toolCalling"?: boolean, // Whether model supports function/tool calling (optional, default: false) + "editTools"?: string[], // List of supported edit tools (optional, default: []) + "temperature"?: number, // Temperature setting (optional, 0.0-2.0, default: 1.0) + "thinking"?: boolean, // Whether model supports thinking/reasoning tokens (optional, default: false) + "vision"?: boolean, // Whether model supports vision/image inputs (optional, default: false) + "requestHeaders"?: Record, // Custom HTTP headers for requests (optional, default: null) + "requiresAPIKey"?: boolean, // Whether model requires API key (optional, default: true) + } + } +} +``` + +## URL Resolution Behavior + +### Base URL Format +The `url` field should contain the **base Azure endpoint URL** without the API path: + +```json +// ✅ Correct - base URL only +"url": "https://my-resource.openai.azure.com" +"url": "https://my-resource.models.ai.azure.com" + +// ❌ Wrong - includes API path +"url": "https://my-resource.openai.azure.com/openai/deployments/gpt-4/chat/completions" +``` + +### Deployment Types + +#### 1. Chat Completions API (`deploymentType: "completions"`) +**Default deployment type.** Uses the standard Azure OpenAI Chat Completions endpoint. + +- **URL Pattern**: Deployment name is included in the URL path +- **Azure OpenAI endpoints** (`openai.azure.com`): + - Resolved URL: `{url}/openai/deployments/{deploymentName}/chat/completions?api-version={apiVersion}` +- **Azure AI endpoints** (`models.ai.azure.com`, `inference.ml.azure.com`): + - Resolved URL: `{url}/v1/chat/completions` + +**Example Configuration:** +```json +{ + "chat.azureModels": { + "gpt-4-turbo": { + "name": "GPT-4 Turbo", + "url": "https://my-resource.openai.azure.com", + "deploymentType": "completions", + "deploymentName": "gpt-4-turbo-deployment", + "apiVersion": "2024-08-01-preview", + "maxInputTokens": 128000, + "maxOutputTokens": 4096, + "toolCalling": true, + "temperature": 0.7, + "thinking": false, + "vision": false + } + } +} +``` + +#### 2. Responses API (`deploymentType: "responses"`) +Uses the Azure OpenAI Responses API for streaming responses with structured outputs. + +- **URL Pattern**: Deployment name is sent in the request body, NOT in URL +- **Azure OpenAI endpoints** (`openai.azure.com`): + - Resolved URL: `{url}/openai/responses?api-version={apiVersion}` +- **Azure AI endpoints** (`models.ai.azure.com`, `inference.ml.azure.com`): + - Resolved URL: `{url}/v1/responses?api-version={apiVersion}` +- **Model Field**: The `deploymentName` is passed as the `model` field in the request body + +**Example Configuration:** +```json +{ + "chat.azureModels": { + "o1-preview": { + "name": "OpenAI o1-preview", + "url": "https://my-resource.openai.azure.com", + "deploymentType": "responses", + "deploymentName": "o1-preview-deployment", + "apiVersion": "2025-01-01-preview", + "maxInputTokens": 128000, + "maxOutputTokens": 32768, + "toolCalling": false, + "temperature": 1.0, + "thinking": true, + "vision": true + } + } +} +``` + +### Deployment Name Behavior + +- **If `deploymentName` is provided**: Uses the specified deployment name +- **If `deploymentName` is omitted**: Falls back to using `modelId` as the deployment name +- **For Completions API**: Deployment name is included in the URL path +- **For Responses API**: Deployment name is sent as the `model` field in the request body + +## Implementation Details + +### URL Resolution Logic (`resolveAzureUrl`) + +The `resolveAzureUrl` function in `azureProvider.ts` handles URL construction: + +1. **Strips trailing slashes and `/v1` suffixes** from base URLs +2. **Detects endpoint type** based on URL patterns: + - Azure AI: `models.ai.azure.com`, `inference.ml.azure.com` + - Azure OpenAI: `openai.azure.com`, `cognitiveservices.azure.com` +3. **Applies deployment-specific URL patterns** based on `deploymentType` +4. **Uses defaults** if optional fields are omitted: + - `deploymentType`: `"completions"` + - `deploymentName`: Falls back to `modelId` + - `apiVersion`: `"2025-01-01-preview"` + +### Model Info Resolution (`getModelInfo`) + +The `getModelInfo` method in `AzureBYOKModelProvider`: + +1. **Retrieves deployment configuration** from settings +2. **For Responses API**: Overrides the model name to use `deploymentName` (sent in request body) +3. **For Completions API**: Uses `deploymentName` in URL path +4. **Sets `modelInfo.id`** to the deployment name for proper API routing +5. **Configures `supported_endpoints`**: + - Responses API: `[ModelSupportedEndpoint.Responses]` + - Completions API: `[ModelSupportedEndpoint.ChatCompletions]` +6. **Applies temperature** from configuration if specified + +### API Key Management + +- API keys are stored securely using VS Code's secrets storage +- Keys are stored per-model using the pattern: `copilot-byok-Azure-{modelId}-api-key` +- The `requiresAPIKey` field controls whether authentication is required (default: `true`) +- Users configure API keys through the UI or via commands + +## Best Practices + +1. **Use explicit deployment names**: Always specify `deploymentName` to avoid confusion with model IDs +2. **Match API versions**: Use the API version that matches your Azure deployment capabilities +3. **Set accurate token limits**: Configure `maxInputTokens` and `maxOutputTokens` based on your deployment +4. **Enable appropriate capabilities**: Set `toolCalling`, `thinking` and `vision` flags based on model support +5. **Test endpoint URLs**: Verify base URLs are correct and accessible before adding models +6. **Group related models**: Use descriptive model IDs for easy identification in the UI +7. **Document custom configurations**: Add comments in settings.json to explain non-standard configurations + +## Troubleshooting + +### Common Issues + +**Issue**: Model not appearing in selection +- **Check**: Ensure all required fields are present in configuration + +**Issue**: 404 errors when using model +- **Check**: Verify `deploymentName` matches your Azure deployment +- **Check**: Ensure `url` points to the correct Azure resource +- **Check**: Confirm `apiVersion` is supported by your deployment + +**Issue**: Unsupported endpoint errors +- **Check**: Verify `deploymentType` matches your deployment's API type +- **Check**: For reasoning models (o1), use `deploymentType: "responses"` + +**Issue**: Model name mismatches in API calls +- **For Responses API**: Ensure `deploymentName` is set (it's sent as the model name) +- **For Completions API**: Deployment name is in URL, not request body + +## Related Files + +- Implementation: `src/extension/byok/vscode-node/azureProvider.ts` +- Base provider: `src/extension/byok/vscode-node/customOAIProvider.ts` +- Configuration: `src/platform/configuration/common/configurationService.ts` +- Storage: `src/extension/byok/vscode-node/byokStorageService.ts` diff --git a/package.json b/package.json index 4f4a722f27..b916d5df52 100644 --- a/package.json +++ b/package.json @@ -3035,13 +3035,21 @@ "type": "string", "description": "URL endpoint for the Azure model" }, - "toolCalling": { - "type": "boolean", - "description": "Whether the model supports tool calling" + "deploymentName": { + "type": "string", + "description": "Azure deployment name for the model" }, - "vision": { - "type": "boolean", - "description": "Whether the model supports vision capabilities" + "deploymentType": { + "enum": [ + "completions", + "responses" + ], + "default": "completions", + "description": "Type of Azure deployment" + }, + "apiVersion": { + "type": "string", + "description": "Azure OpenAI API version to use" }, "maxInputTokens": { "type": "number", @@ -3051,11 +3059,38 @@ "type": "number", "description": "Maximum number of output tokens supported by the model" }, + "toolCalling": { + "type": "boolean", + "description": "Whether the model supports tool calling" + }, + "editTools": { + "type": "array", + "description": "List of edit tools supported by the model. If this is not configured, the editor will try multiple edit tools and pick the best one.\n\n- 'find-replace': Find and replace text in a document.\n- 'multi-find-replace': Find and replace text in a document.\n- 'apply-patch': A file-oriented diff format used by some OpenAI models\n- 'code-rewrite': A general but slower editing tool that allows the model to rewrite and code snippet and provide only the replacement to the editor.", + "items": { + "type": "string", + "enum": [ + "find-replace", + "multi-find-replace", + "apply-patch", + "code-rewrite" + ] + } + }, + "temperature": { + "type": "number", + "description": "Temperature parameter for model responses (typically 0.0 to 2.0)", + "minimum": 0, + "maximum": 2 + }, "thinking": { "type": "boolean", "default": false, "description": "Whether the model supports thinking capabilities" }, + "vision": { + "type": "boolean", + "description": "Whether the model supports vision capabilities" + }, "requestHeaders": { "type": "object", "description": "Additional HTTP headers to include with requests to this model. These reserved headers are not allowed and ignored if present: forbidden request headers (https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_request_header), forwarding headers ('forwarded', 'x-forwarded-for', 'x-forwarded-host', 'x-forwarded-proto'), and others ('api-key', 'authorization', 'content-type', 'openai-intent', 'x-github-api-version', 'x-initiator', 'x-interaction-id', 'x-interaction-type', 'x-onbehalf-extension-id', 'x-request-id', 'x-vscode-user-agent-library-version'). Pattern-based forbidden headers ('proxy-*', 'sec-*', 'x-http-method*' with forbidden methods) are also blocked.", @@ -3067,8 +3102,6 @@ "required": [ "name", "url", - "toolCalling", - "vision", "maxInputTokens", "maxOutputTokens" ], @@ -3097,23 +3130,6 @@ "type": "boolean", "description": "Whether the model supports tool calling" }, - "vision": { - "type": "boolean", - "description": "Whether the model supports vision capabilities" - }, - "maxInputTokens": { - "type": "number", - "description": "Maximum number of input tokens supported by the model" - }, - "maxOutputTokens": { - "type": "number", - "description": "Maximum number of output tokens supported by the model" - }, - "requiresAPIKey": { - "type": "boolean", - "description": "Whether the model requires an API key for authentication", - "default": true - }, "editTools": { "type": "array", "description": "List of edit tools supported by the model. If this is not configured, the editor will try multiple edit tools and pick the best one.\n\n- 'find-replace': Find and replace text in a document.\n- 'multi-find-replace': Find and replace text in a document.\n- 'apply-patch': A file-oriented diff format used by some OpenAI models\n- 'code-rewrite': A general but slower editing tool that allows the model to rewrite and code snippet and provide only the replacement to the editor.", @@ -3127,24 +3143,45 @@ ] } }, + "temperature": { + "type": "number", + "description": "Temperature parameter for model responses (typically 0.0 to 2.0)", + "minimum": 0, + "maximum": 2 + }, "thinking": { "type": "boolean", "default": false, "description": "Whether the model supports thinking capabilities" }, + "vision": { + "type": "boolean", + "description": "Whether the model supports vision capabilities" + }, + "maxInputTokens": { + "type": "number", + "description": "Maximum number of input tokens supported by the model" + }, + "maxOutputTokens": { + "type": "number", + "description": "Maximum number of output tokens supported by the model" + }, "requestHeaders": { "type": "object", "description": "Additional HTTP headers to include with requests to this model. These reserved headers are not allowed and ignored if present: forbidden request headers (https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_request_header), forwarding headers ('forwarded', 'x-forwarded-for', 'x-forwarded-host', 'x-forwarded-proto'), and others ('api-key', 'authorization', 'content-type', 'openai-intent', 'x-github-api-version', 'x-initiator', 'x-interaction-id', 'x-interaction-type', 'x-onbehalf-extension-id', 'x-request-id', 'x-vscode-user-agent-library-version'). Pattern-based forbidden headers ('proxy-*', 'sec-*', 'x-http-method*' with forbidden methods) are also blocked.", "additionalProperties": { "type": "string" } + }, + "requiresAPIKey": { + "type": "boolean", + "description": "Whether the model requires an API key for authentication", + "default": true } }, "required": [ "name", "url", - "toolCalling", - "vision", "maxInputTokens", "maxOutputTokens", "requiresAPIKey" diff --git a/src/extension/byok/common/byokProvider.ts b/src/extension/byok/common/byokProvider.ts index b4c1bd4928..8d23d3c1f1 100644 --- a/src/extension/byok/common/byokProvider.ts +++ b/src/extension/byok/common/byokProvider.ts @@ -55,6 +55,7 @@ export interface BYOKModelCapabilities { toolCalling: boolean; vision: boolean; thinking?: boolean; + temperature?: number; editTools?: EndpointEditToolName[]; requestHeaders?: Record; } @@ -153,6 +154,9 @@ export function resolveModelInfo(modelId: string, providerName: string, knownMod if (knownModelInfo?.requestHeaders && Object.keys(knownModelInfo.requestHeaders).length > 0) { modelInfo.requestHeaders = { ...knownModelInfo.requestHeaders }; } + if (knownModelInfo?.temperature !== undefined) { + modelInfo.temperature = knownModelInfo.temperature; + } return modelInfo; } diff --git a/src/extension/byok/node/openAIEndpoint.ts b/src/extension/byok/node/openAIEndpoint.ts index 63fd236ccb..7a146de833 100644 --- a/src/extension/byok/node/openAIEndpoint.ts +++ b/src/extension/byok/node/openAIEndpoint.ts @@ -113,6 +113,7 @@ export class OpenAIEndpoint extends ChatEndpoint { private static readonly _maxCustomHeaderCount = 20; private readonly _customHeaders: Record; + private readonly _temperature: number | undefined; constructor( _modelMetadata: IChatModelInformation, protected readonly _apiKey: string, @@ -144,6 +145,7 @@ export class OpenAIEndpoint extends ChatEndpoint { logService ); this._customHeaders = this._sanitizeCustomHeaders(_modelMetadata.requestHeaders); + this._temperature = _modelMetadata.temperature; } private _sanitizeCustomHeaders(headers: Readonly> | undefined): Record { @@ -289,13 +291,27 @@ export class OpenAIEndpoint extends ChatEndpoint { } if (body) { + // Apply temperature from config if specified (before thinking model checks) + if (this._temperature !== undefined) { + body.temperature = this._temperature; + } + if (this.modelMetadata.capabilities.supports.thinking) { + // Thinking models don't support temperature parameter delete body.temperature; - body['max_completion_tokens'] = body.max_tokens; - delete body.max_tokens; + // Thinking models use max_completion_tokens instead of max_tokens + if (typeof body.max_tokens !== 'undefined') { + body['max_completion_tokens'] = body.max_tokens; + delete body.max_tokens; + } } - // Removing max tokens defaults to the maximum which is what we want for BYOK - delete body.max_tokens; + else { + // For non-thinking models, removing max_tokens defaults to the maximum allowed value, which is what we want for BYOK + if (typeof body.max_tokens !== 'undefined') { + delete body.max_tokens; + } + } + if (!this.useResponsesApi && body.stream) { body['stream_options'] = { 'include_usage': true }; } diff --git a/src/extension/byok/vscode-node/azureProvider.ts b/src/extension/byok/vscode-node/azureProvider.ts index 673e8ca845..0e6b084c07 100644 --- a/src/extension/byok/vscode-node/azureProvider.ts +++ b/src/extension/byok/vscode-node/azureProvider.ts @@ -4,13 +4,47 @@ *--------------------------------------------------------------------------------------------*/ import { ConfigKey, IConfigurationService } from '../../../platform/configuration/common/configurationService'; +import { EndpointEditToolName, IChatModelInformation, ModelSupportedEndpoint } from '../../../platform/endpoint/common/endpointProvider'; import { ILogService } from '../../../platform/log/common/logService'; import { IExperimentationService } from '../../../platform/telemetry/common/nullExperimentationService'; import { IInstantiationService } from '../../../util/vs/platform/instantiation/common/instantiation'; +import { BYOKModelCapabilities } from '../common/byokProvider'; import { IBYOKStorageService } from './byokStorageService'; import { CustomOAIBYOKModelProvider, hasExplicitApiPath } from './customOAIProvider'; -export function resolveAzureUrl(modelId: string, url: string): string { +export interface AzureUrlOptions { + deploymentType: 'completions' | 'responses'; + deploymentName: string; + apiVersion: string; +} + +interface AzureModelConfig { + name: string; + url: string; + deploymentType?: 'completions' | 'responses'; + deploymentName?: string; + apiVersion?: string; + maxInputTokens: number; + maxOutputTokens: number; + toolCalling?: boolean; + editTools?: EndpointEditToolName[]; + thinking?: boolean; + vision?: boolean; + temperature?: number; + requiresAPIKey?: boolean; + requestHeaders?: Record; +} + +function createAzureUrlOptions(modelId: string, config?: Partial): AzureUrlOptions { + return { + deploymentType: config?.deploymentType ?? 'completions', + deploymentName: config?.deploymentName ?? modelId, + apiVersion: config?.apiVersion ?? '2025-01-01-preview' + }; +} + +export function resolveAzureUrl(modelId: string, url: string, options: AzureUrlOptions): string { + // The fully resolved url was already passed in if (hasExplicitApiPath(url)) { return url; @@ -25,15 +59,40 @@ export function resolveAzureUrl(modelId: string, url: string): string { url = url.slice(0, -3); } - // Default to chat completions for base URLs - const defaultApiPath = '/chat/completions'; + const { deploymentName, deploymentType, apiVersion } = options; + + // Determine if this is an Azure OpenAI endpoint (requires deployment name in path) + const isAzureOpenAIEndpointv1 = url.includes('models.ai.azure.com') || url.includes('inference.ml.azure.com'); + const isAzureOpenAIEndpoint = url.includes('openai.azure.com') || url.includes('cognitiveservices.azure.com'); + + if (deploymentType === 'responses') { + // Handle Responses API + // Deployment name is passed in the request body as 'model' parameter, not in URL + let resolvedUrl: string; + if (isAzureOpenAIEndpointv1) { + resolvedUrl = `${url}/v1/responses?api-version=${apiVersion}`; + } else if (isAzureOpenAIEndpoint) { + resolvedUrl = `${url}/openai/responses?api-version=${apiVersion}`; + } else { + throw new Error(`Unrecognized Azure deployment URL for Responses API: ${url}`); + } - if (url.includes('models.ai.azure.com') || url.includes('inference.ml.azure.com')) { - return `${url}/v1${defaultApiPath}`; - } else if (url.includes('openai.azure.com')) { - return `${url}/openai/deployments/${modelId}${defaultApiPath}?api-version=2025-01-01-preview`; + return resolvedUrl; + } else if (deploymentType === 'completions') { + // Handle Chat Completions API (default) + const defaultApiPath = '/chat/completions'; + let resolvedUrl: string; + + if (isAzureOpenAIEndpointv1) { + resolvedUrl = `${url}/v1${defaultApiPath}`; + } else if (isAzureOpenAIEndpoint) { + resolvedUrl = `${url}/openai/deployments/${deploymentName}${defaultApiPath}?api-version=${apiVersion}`; + } else { + throw new Error(`Unrecognized Azure deployment URL: ${url}`); + } + return resolvedUrl; } else { - throw new Error(`Unrecognized Azure deployment URL: ${url}`); + throw new Error(`Invalid deployment type specified for model ${modelId}: ${deploymentType}`); } } @@ -41,18 +100,18 @@ export class AzureBYOKModelProvider extends CustomOAIBYOKModelProvider { static override readonly providerName = 'Azure'; constructor( - byokStorageService: IBYOKStorageService, - @IConfigurationService configurationService: IConfigurationService, - @ILogService logService: ILogService, - @IInstantiationService instantiationService: IInstantiationService, - @IExperimentationService experimentationService: IExperimentationService + _byokStorageService: IBYOKStorageService, + @IConfigurationService _configurationService: IConfigurationService, + @ILogService _logService: ILogService, + @IInstantiationService _instantiationService: IInstantiationService, + @IExperimentationService _experimentationService: IExperimentationService ) { super( - byokStorageService, - configurationService, - logService, - instantiationService, - experimentationService + _byokStorageService, + _configurationService, + _logService, + _instantiationService, + _experimentationService ); // Override the instance properties this.providerName = AzureBYOKModelProvider.providerName; @@ -63,6 +122,39 @@ export class AzureBYOKModelProvider extends CustomOAIBYOKModelProvider { } protected override resolveUrl(modelId: string, url: string): string { - return resolveAzureUrl(modelId, url); + // Get model config to access deployment options + const modelConfig = this._configurationService?.getConfig(this.getConfigKey()) as Record | undefined; + const config = modelConfig?.[modelId]; + const options = createAzureUrlOptions(modelId, config); + return resolveAzureUrl(modelId, url, options); + } + + protected override async getModelInfo(modelId: string, apiKey: string | undefined, modelCapabilities?: BYOKModelCapabilities): Promise { + // Get model config to check deployment type and deployment name + const configKey = this.getConfigKey(); + const modelConfig = this._configurationService.getConfig(configKey); + + // Safely access the model-specific config + let config: AzureModelConfig | undefined; + if (modelConfig && typeof modelConfig === 'object' && modelId in modelConfig) { + config = (modelConfig as Record)[modelId]; + } + + const options = createAzureUrlOptions(modelId, config); + const modelInfo = await super.getModelInfo(modelId, apiKey, modelCapabilities); + + // Override modelInfo.id with the deployment name (deployment name is also handled). + // This is required because Azure OpenAI uses the deployment name for API routing. + modelInfo.id = options.deploymentName; + + // Set supported endpoints based on deployment type + if (options.deploymentType === 'responses') { + modelInfo.supported_endpoints = [ModelSupportedEndpoint.Responses]; + } else { + // For completions API, only support chat completions + modelInfo.supported_endpoints = [ModelSupportedEndpoint.ChatCompletions]; + } + + return modelInfo; } } diff --git a/src/extension/byok/vscode-node/customOAIProvider.ts b/src/extension/byok/vscode-node/customOAIProvider.ts index 825226dd4c..3e2e5876a7 100644 --- a/src/extension/byok/vscode-node/customOAIProvider.ts +++ b/src/extension/byok/vscode-node/customOAIProvider.ts @@ -44,9 +44,24 @@ export function hasExplicitApiPath(url: string): boolean { return url.includes('/responses') || url.includes('/chat/completions'); } +interface UserModelConfig { + name: string; + url: string; + maxInputTokens: number; + maxOutputTokens: number; + toolCalling?: boolean; + editTools?: EndpointEditToolName[]; + temperature?: number; + thinking?: boolean; + vision?: boolean; + requestHeaders?: Record; + requiresAPIKey: boolean; +} + interface CustomOAIModelInfo extends LanguageModelChatInformation { url: string; thinking: boolean; + temperature?: number; requestHeaders?: Record; } @@ -86,8 +101,8 @@ export class CustomOAIBYOKModelProvider implements BYOKModelProvider }> { - const modelConfig = this._configurationService.getConfig(this.getConfigKey()) as Record }>; + private getUserModelConfig(): Record { + const modelConfig = this._configurationService.getConfig(this.getConfigKey()) as Record; return modelConfig; } @@ -107,13 +122,14 @@ export class CustomOAIBYOKModelProvider implements BYOKModelProvider { + private forward(methodName: K): ChatResponseStream[K] { + const method = this._wrapped[methodName]; + if (typeof method !== 'function') { + this._logService.warn(`[CodeBlockTrackingChatResponseStream] Method '${String(methodName)}' does not exist on the wrapped ChatResponseStream.`); + // Create a proper no-op function that matches the method signature + const noOp = (..._args: any[]): any => { + return undefined; + }; + return noOp as ChatResponseStream[K]; + } + // Preserve the function signature without double casting + const boundMethod = (...args: any[]) => { this._codeBlockProcessor.flush(); - return fc(...args); + return (method as Function).apply(this._wrapped, args); }; + return boundMethod as ChatResponseStream[K]; } - button = this.forward(this._wrapped.button.bind(this._wrapped)); - filetree = this.forward(this._wrapped.filetree.bind(this._wrapped)); - progress = this._wrapped.progress.bind(this._wrapped); - reference = this.forward(this._wrapped.reference.bind(this._wrapped)); - textEdit = this.forward(this._wrapped.textEdit.bind(this._wrapped)); - notebookEdit = this.forward(this._wrapped.notebookEdit.bind(this._wrapped)); - confirmation = this.forward(this._wrapped.confirmation.bind(this._wrapped)); - warning = this.forward(this._wrapped.warning.bind(this._wrapped)); - reference2 = this.forward(this._wrapped.reference2.bind(this._wrapped)); - codeCitation = this.forward(this._wrapped.codeCitation.bind(this._wrapped)); - anchor = this.forward(this._wrapped.anchor.bind(this._wrapped)); - externalEdit = this.forward(this._wrapped.externalEdit.bind(this._wrapped)); - prepareToolInvocation = this.forward(this._wrapped.prepareToolInvocation.bind(this._wrapped)); + button = this.forward('button'); + filetree = this.forward('filetree'); + progress = this.forward('progress'); + reference = this.forward('reference'); + textEdit = this.forward('textEdit'); + notebookEdit = this.forward('notebookEdit'); + confirmation = this.forward('confirmation'); + warning = this.forward('warning'); + reference2 = this.forward('reference2'); + codeCitation = this.forward('codeCitation'); + anchor = this.forward('anchor'); + externalEdit = this.forward('externalEdit'); + prepareToolInvocation = this.forward('prepareToolInvocation'); } diff --git a/src/platform/configuration/common/configurationService.ts b/src/platform/configuration/common/configurationService.ts index c45571f14b..99bff89936 100644 --- a/src/platform/configuration/common/configurationService.ts +++ b/src/platform/configuration/common/configurationService.ts @@ -811,8 +811,8 @@ export namespace ConfigKey { export const CurrentEditorAgentContext = defineSetting('chat.agent.currentEditorContext.enabled', true); /** BYOK */ export const OllamaEndpoint = defineSetting('chat.byok.ollamaEndpoint', 'http://localhost:11434'); - export const AzureModels = defineSetting>('chat.azureModels', {}); - export const CustomOAIModels = defineSetting }>>('chat.customOAIModels', {}); + export const AzureModels = defineSetting>('chat.azureModels', {}); + export const CustomOAIModels = defineSetting }>>('chat.customOAIModels', {}); export const AutoFixDiagnostics = defineExpSetting('chat.agent.autoFix', true); export const NotebookFollowCellExecution = defineSetting('chat.notebook.followCellExecution.enabled', false); export const UseAlternativeNESNotebookFormat = defineExpSetting('chat.notebook.enhancedNextEditSuggestions.enabled', false); diff --git a/src/platform/endpoint/common/endpointProvider.ts b/src/platform/endpoint/common/endpointProvider.ts index d60b3c9c78..4e52fd38d6 100644 --- a/src/platform/endpoint/common/endpointProvider.ts +++ b/src/platform/endpoint/common/endpointProvider.ts @@ -93,6 +93,7 @@ export type IChatModelInformation = IModelAPIResponse & { capabilities: IChatModelCapabilities; urlOrRequestMetadata?: string | RequestMetadata; requestHeaders?: Readonly>; + temperature?: number; }; export function isChatModelInformation(model: IModelAPIResponse): model is IChatModelInformation {