Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
9489e7e
Disable issue reporter submit button while the issue is being submitted
mjbvz May 1, 2026
5115d4b
Minor cleanup for cli credits (#315164)
pwang347 May 8, 2026
a8af3bc
Add AIC to agent debug panel (#315133)
pwang347 May 8, 2026
67279f7
Add snippet support for CURRENT_MILLISECOND, CURRENT_MILLISECONDS_UNI…
Copilot May 8, 2026
89bab60
Clear details on sign out (#315170)
pwang347 May 8, 2026
f6267e5
Merge pull request #313678 from microsoft/dev/mjbvz/busy-swift
mjbvz May 8, 2026
442300c
Snippets: fix comma in serialized regex transform (#315151)
Copilot May 8, 2026
75837b4
Update wording and fix view usage button (#315179)
pwang347 May 8, 2026
c15ec12
Remove Agents app testing from sanity tests (#315180)
dmitrivMS May 8, 2026
135da07
BYOK: support per-model reasoning_effort across OpenAI-compatible pro…
vijayupadya May 8, 2026
d67c9fd
Refactor Copilot CLI agent resolution with enhanced caching (#315175)
DonJayamanne May 8, 2026
baedb11
fix: include sidekick YAML definitions in .vscodeignore (#315132)
DonJayamanne May 8, 2026
2230fcd
fix: disable session controller for CLI by default (#315084)
DonJayamanne May 8, 2026
80b2b69
Keep historical user messages cache-safe (#315194)
bhavyaus May 8, 2026
d610456
Agents - show label of the running action + progress icon (#315200)
lszomoru May 8, 2026
fa785d6
Agents web: no hosts screen (#315113)
osortega May 8, 2026
d59635a
Agents - set the title/aria label for the button when the custom labe…
lszomoru May 8, 2026
ab6beec
Improves animated value (#315213)
hediet May 8, 2026
5df5c92
add testplan item template
benibenj May 8, 2026
a4a9f2c
Harden snippet session against null decorations and selection/placeho…
dmitrivMS May 8, 2026
ca7f363
better new session hover
benibenj May 8, 2026
431141f
update naming
benibenj May 8, 2026
3c96730
Agents - do not pass the session metadata to commands (#315214)
lszomoru May 8, 2026
ca56b78
Add command to dump settings schema (#315219)
alexr00 May 8, 2026
373cd0d
Move risk assessment above buttons (#315215)
chrmarti May 8, 2026
760844f
Merge pull request #315222 from microsoft/benibenj/envious-gibbon
benibenj May 8, 2026
18ff720
Merge pull request #315221 from microsoft/benibenj/fantastic-dragon
benibenj May 8, 2026
5a070ba
Fix comment widget not always showing (#315227)
alexr00 May 8, 2026
b482e07
Reduces screenshot report size
hediet May 8, 2026
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
18 changes: 18 additions & 0 deletions .github/ISSUE_TEMPLATE/team/testplan_item.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
name: Test Plan Item
about: Create test plan item for endgame
title: ""
labels: testplan-item
assignees: ""
---

Refs: <!-- Refer to the issue that this test plan item is testing. -->

- [ ] anyOS
- [ ] anyOS

Complexity: 4

---

<!-- Please write your test here. -->
2 changes: 1 addition & 1 deletion build/lib/screenshotDiffReport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
const COMMENT_MARKER = '<!-- screenshot-diff-report -->';
const EXPAND_FIRST_N = 5;
const EXCLUDED_LABELS = new Set(['animated', 'flaky']);
const MAX_BODY_BYTES = 750 * 1024;
const MAX_BODY_BYTES = 300 * 1024;

// ---------------------------------------------------------------------------
// Pixel-level image comparison
Expand Down
1 change: 1 addition & 0 deletions extensions/copilot/.vscodeignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ node_modules/@github/copilot/sharp/**
!node_modules/@github/copilot/sdk/worker/*.js
!node_modules/@github/copilot/sdk/sharp/**
!node_modules/@github/copilot/sdk/definitions/*.yaml
!node_modules/@github/copilot/sdk/definitions/sidekick/*.yaml
!CHANGELOG.md
!README.md
!package.json
Expand Down
32 changes: 31 additions & 1 deletion extensions/copilot/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1951,6 +1951,21 @@
"default": false,
"markdownDescription": "Whether Zero Data Retention (ZDR) is enabled for this endpoint. When `true`, `previous_response_id` will not be sent in requests via Responses API."
},
"supportsReasoningEffort": {
"type": "array",
"markdownDescription": "Reasoning effort levels the model accepts (e.g. `[\"low\", \"medium\", \"high\"]`). When set, a `Thinking Effort` picker is shown in the model picker and the chosen value is forwarded to the model. Levels supported by mainstream OpenAI-compatible servers are `minimal`, `low`, `medium`, `high`.",
"items": {
"type": "string"
}
},
"reasoningEffortFormat": {
"type": "string",
"enum": [
"chat-completions",
"responses"
],
"markdownDescription": "Body shape used to forward the reasoning effort to the model. `chat-completions` sends a top-level `reasoning_effort` string. `responses` sends a nested `reasoning.effort` object. When unset the format follows the URL: `/responses` \u2192 nested, otherwise top-level."
},
"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.",
Expand Down Expand Up @@ -2050,6 +2065,21 @@
"default": false,
"markdownDescription": "Whether Zero Data Retention (ZDR) is enabled for this endpoint. When `true`, `previous_response_id` will not be sent in requests via Responses API."
},
"supportsReasoningEffort": {
"type": "array",
"markdownDescription": "Reasoning effort levels the model accepts (e.g. `[\"low\", \"medium\", \"high\"]`). When set, a `Thinking Effort` picker is shown in the model picker and the chosen value is forwarded to the model. Levels supported by mainstream OpenAI-compatible servers are `minimal`, `low`, `medium`, `high`.",
"items": {
"type": "string"
}
},
"reasoningEffortFormat": {
"type": "string",
"enum": [
"chat-completions",
"responses"
],
"markdownDescription": "Body shape used to forward the reasoning effort to the model. `chat-completions` sends a top-level `reasoning_effort` string. `responses` sends a nested `reasoning.effort` object. When unset the format follows the URL: `/responses` \u2192 nested, otherwise top-level."
},
"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.",
Expand Down Expand Up @@ -4782,7 +4812,7 @@
},
"github.copilot.chat.cli.sessionController.enabled": {
"type": "boolean",
"default": true,
"default": false,
"markdownDescription": "%github.copilot.config.cli.sessionController.enabled%",
"tags": [
"advanced"
Expand Down
13 changes: 11 additions & 2 deletions extensions/copilot/src/extension/byok/common/byokProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ export interface BYOKModelCapabilities {
supportedEndpoints?: ModelSupportedEndpoint[];
zeroDataRetentionEnabled?: boolean;
supportsReasoningEffort?: string[];
/**
* Override the body shape used to forward the reasoning effort to the model.
* - `'chat-completions'`: top-level `reasoning_effort` (default for `/chat/completions`).
* - `'responses'`: nested `reasoning.effort` (default for `/responses`).
* If unset the format is inferred from whether the endpoint uses the Responses API.
*/
reasoningEffortFormat?: 'chat-completions' | 'responses';
}

export interface BYOKModelRegistry {
Expand Down Expand Up @@ -108,7 +115,8 @@ export function resolveModelInfo(modelId: string, providerName: string, knownMod
tool_calls: !!knownModelInfo?.toolCalling,
vision: !!knownModelInfo?.vision,
thinking: !!knownModelInfo?.thinking,
adaptive_thinking: !!knownModelInfo?.adaptiveThinking
adaptive_thinking: !!knownModelInfo?.adaptiveThinking,
reasoning_effort: knownModelInfo?.supportsReasoningEffort
},
tokenizer: TokenizerType.O200K,
limits: {
Expand All @@ -121,7 +129,8 @@ export function resolveModelInfo(modelId: string, providerName: string, knownMod
is_chat_fallback: false,
model_picker_enabled: true,
supported_endpoints: knownModelInfo?.supportedEndpoints,
zeroDataRetentionEnabled: knownModelInfo?.zeroDataRetentionEnabled
zeroDataRetentionEnabled: knownModelInfo?.zeroDataRetentionEnabled,
reasoningEffortFormat: knownModelInfo?.reasoningEffortFormat
};
if (knownModelInfo?.requestHeaders && Object.keys(knownModelInfo.requestHeaders).length > 0) {
modelInfo.requestHeaders = { ...knownModelInfo.requestHeaders };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import { describe, expect, it } from 'vitest';
import { byokKnownModelToAPIInfo, BYOKModelCapabilities } from '../byokProvider';
import { byokKnownModelToAPIInfo, BYOKModelCapabilities, resolveModelInfo } from '../byokProvider';

describe('byokKnownModelToAPIInfo', () => {
const baseCapabilities: BYOKModelCapabilities = {
Expand Down Expand Up @@ -43,3 +43,31 @@ describe('byokKnownModelToAPIInfo', () => {
expect(info.capabilities.editTools).toBeUndefined();
});
});

describe('resolveModelInfo', () => {
const baseCapabilities: BYOKModelCapabilities = {
name: 'TestModel',
maxInputTokens: 1000,
maxOutputTokens: 100,
toolCalling: true,
vision: false,
};

it('propagates supportsReasoningEffort and reasoningEffortFormat from BYOK capabilities into chat-endpoint inputs', () => {
const info = resolveModelInfo('m1', 'TestProvider', undefined, {
...baseCapabilities,
supportsReasoningEffort: ['low', 'medium', 'high'],
reasoningEffortFormat: 'responses',
});

expect(info.capabilities.supports.reasoning_effort).toEqual(['low', 'medium', 'high']);
expect(info.reasoningEffortFormat).toBe('responses');
});

it('omits the reasoning effort capability when the model does not declare it', () => {
const info = resolveModelInfo('m1', 'TestProvider', undefined, baseCapabilities);

expect(info.capabilities.supports.reasoning_effort).toBeUndefined();
expect(info.reasoningEffortFormat).toBeUndefined();
});
});
37 changes: 36 additions & 1 deletion extensions/copilot/src/extension/byok/node/openAIEndpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import type { CancellationToken } from 'vscode';
import { IChatMLFetcher } from '../../../platform/chat/common/chatMLFetcher';
import { ChatFetchResponseType, ChatResponse } from '../../../platform/chat/common/commonTypes';
import { IConfigurationService } from '../../../platform/configuration/common/configurationService';
import { ConfigKey, IConfigurationService } from '../../../platform/configuration/common/configurationService';
import { IDomainService } from '../../../platform/endpoint/common/domainService';
import { IChatModelInformation } from '../../../platform/endpoint/common/endpointProvider';
import { ChatEndpoint } from '../../../platform/endpoint/node/chatEndpoint';
Expand Down Expand Up @@ -250,6 +250,7 @@ export class OpenAIEndpoint extends ChatEndpoint {
// Don't use a response ID from CAPI or when zero data retention is enabled
body.previous_response_id = undefined;
}
this._applyReasoningEffort(body, options);
return body;
} else if (this.useMessagesApi) {
// Delegate to base ChatEndpoint for Messages API dispatch
Expand All @@ -263,10 +264,44 @@ export class OpenAIEndpoint extends ChatEndpoint {
}
};
const body = createCapiRequestBody(options, this.model, callback);
this._applyReasoningEffort(body, options);
return body;
}
}

/**
* Forwards the per-request reasoning effort to the model body in the shape the endpoint expects.
* Default shape mirrors the API path (`Responses` \u2192 nested `reasoning.effort`, `Chat Completions` \u2192 top-level `reasoning_effort`).
* `IChatModelInformation.reasoningEffortFormat` overrides the default so users hosting OpenAI-compatible servers
* with diverging conventions (e.g. nested `reasoning.effort` on `/chat/completions`) can opt in deterministically.
*/
private _applyReasoningEffort(body: IEndpointBody, options: ICreateEndpointBodyOptions): void {
const supports = this.supportsReasoningEffort;
if (!supports?.length) {
return;
}
const format = this.modelMetadata.reasoningEffortFormat
?? (this.useResponsesApi ? 'responses' : 'chat-completions');
const override = this._configurationService.getConfig(ConfigKey.Advanced.ReasoningEffortOverride);
const requested = override || options.modelCapabilities?.reasoningEffort || body.reasoning?.effort || body.reasoning_effort;
const effort = requested && supports.includes(requested) ? requested : undefined;
// Scrub any pre-populated effort first so unsupported values (e.g. the hard-coded `medium` default
// from `createResponsesRequestBody`) cannot leak through, then write the resolved value into the
// expected shape.
if (body.reasoning) {
const { effort: _drop, ...rest } = body.reasoning;
body.reasoning = Object.keys(rest).length > 0 ? rest : undefined;
}
body.reasoning_effort = undefined;
if (effort) {
if (format === 'responses') {
body.reasoning = { ...body.reasoning, effort };
} else {
body.reasoning_effort = effort;
}
}
}

override interceptBody(body: IEndpointBody | undefined): void {
super.interceptBody(body);
// TODO @lramos15 - We should do this for all models and not just here
Expand Down
Loading
Loading