Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4067603
chat: use manage settings link for admin-unavailable models
isidorn Feb 20, 2026
d1f34d5
refactor: remove redundant 'id' property from model control entries i…
sandy081 Feb 20, 2026
643712d
clean up (#296490)
sandy081 Feb 20, 2026
efa6580
chat - add `product.overrides.json` to `git.worktreeIncludeFiles` (#2…
bpasero Feb 20, 2026
3d96e62
sessions - tweak customization sidebar styling (#296491)
bpasero Feb 20, 2026
75fd74f
GitService - add the ability to get list of references (#296486)
lszomoru Feb 20, 2026
7a0b83f
remove id (#296497)
sandy081 Feb 20, 2026
43edce9
Merge origin/main into isidor/chat-model-picker-manage-settings-link
isidorn Feb 20, 2026
7f4996f
sessions - separate protocol handler (#296514)
bpasero Feb 20, 2026
5ed0d0d
add logging (#296518)
sandy081 Feb 20, 2026
9529b11
Git - handle multiple extension host process (#296510)
lszomoru Feb 20, 2026
f71c31e
Show stop button when question is active
roblourens Feb 20, 2026
da43266
fix hygeien
isidorn Feb 20, 2026
7a0848c
:up: distro (#296526)
bpasero Feb 20, 2026
b57e5ff
Merge pull request #296480 from microsoft/isidor/chat-model-picker-ma…
isidorn Feb 20, 2026
0e6e2ba
Merge pull request #296524 from microsoft/roblou/chemical-narwhal
roblourens Feb 20, 2026
de68742
refactor: remove upgradePlanUrl from model picker functions and tests
isidorn Feb 20, 2026
df22d31
remove ugly native hover
isidorn Feb 20, 2026
da77744
Fix #296523 (#296530)
sandy081 Feb 20, 2026
0432ab0
if user has unselected options, respect that (#296387)
meganrogge Feb 20, 2026
c737ece
Merge pull request #296537 from microsoft/isidorn/adorable-damselfly
isidorn Feb 20, 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
12 changes: 7 additions & 5 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,10 @@
// --- TypeScript ---
"typescript.experimental.useTsgo": true,
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.preferences.importModuleSpecifier": "relative",
"typescript.preferences.quoteStyle": "single",
"js/ts.preferences.importModuleSpecifier": "relative",
"js/ts.preferences.quoteStyle": "single",
"typescript.tsc.autoDetect": "off",
"typescript.preferences.autoImportFileExcludePatterns": [
"js/ts.preferences.autoImportFileExcludePatterns": [
"@xterm/xterm",
"@xterm/headless",
"node-pty",
Expand Down Expand Up @@ -144,6 +144,9 @@
"ts": "warning",
"eslint": "warning"
},
"git.worktreeIncludeFiles": [
"product.overrides.json"
],
// --- GitHub ---
"githubPullRequests.experimental.createView": true,
"githubPullRequests.assignCreated": "${user}",
Expand Down Expand Up @@ -199,12 +202,11 @@
"sash"
],
// --- Workbench ---
// "application.experimental.rendererProfiling": true, // https://github.com/microsoft/vscode/issues/265654
"editor.aiStats.enabled": true, // Team selfhosting on ai stats
"azureMcp.enabledServices": [
"kusto" // Needed for kusto tool in data.prompt.md
],
"azureMcp.serverMode": "all",
"azureMcp.readOnly": true,
"debug.breakpointsView.presentation": "tree"
"debug.breakpointsView.presentation": "tree",
}
3 changes: 2 additions & 1 deletion build/gulpfile.vscode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ function packageTask(platform: string, arch: string, sourceFolderName: string, d

const isInsiderOrExploration = quality === 'insider' || quality === 'exploration';
const embedded = isInsiderOrExploration
? (product as typeof product & { embedded?: { nameShort: string; nameLong: string; applicationName: string; dataFolderName: string; darwinBundleIdentifier: string } }).embedded
? (product as typeof product & { embedded?: { nameShort: string; nameLong: string; applicationName: string; dataFolderName: string; darwinBundleIdentifier: string; urlProtocol: string } }).embedded
: undefined;

const packageSubJsonStream = isInsiderOrExploration
Expand All @@ -409,6 +409,7 @@ function packageTask(platform: string, arch: string, sourceFolderName: string, d
json.applicationName = embedded.applicationName;
json.dataFolderName = embedded.dataFolderName;
json.darwinBundleIdentifier = embedded.darwinBundleIdentifier;
json.urlProtocol = embedded.urlProtocol;
return json;
}))
.pipe(rename('product.sub.json'))
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "code-oss-dev",
"version": "1.110.0",
"distro": "85914d5a600261a53306190177be48aa8f0cdfb4",
"distro": "bd187e4508a244500eb533c56e5cccb6801a699c",
"author": {
"name": "Microsoft Corporation"
},
Expand Down Expand Up @@ -245,4 +245,4 @@
"optionalDependencies": {
"windows-foreground-love": "0.6.1"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ export class AICustomizationManagementEditor extends EditorPane {
layout: (width, _, height) => {
this.sidebarContainer.style.width = `${width}px`;
if (height !== undefined) {
const listHeight = height - 24;
const listHeight = height - 8;
this.sectionsList.layout(listHeight, width);
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,19 @@
flex-direction: column;
height: 100%;
overflow: hidden;
border-top: 1px solid var(--vscode-panel-border);
}

/* Sidebar */
.ai-customization-management-editor .management-sidebar {
background-color: var(--vscode-sideBar-background);
height: 100%;
overflow: hidden;
border-right: 1px solid var(--vscode-panel-border);
}

.ai-customization-management-editor .sidebar-content {
height: 100%;
padding: 12px 0 12px 4px;
padding: 4px;
box-sizing: border-box;
display: flex;
flex-direction: column;
}
Expand All @@ -41,7 +40,6 @@
padding: 4px 8px;
gap: 10px;
cursor: pointer;
margin: 1px 6px;
border-radius: 4px;
transition: background-color 0.1s ease, opacity 0.1s ease;
}
Expand Down
43 changes: 36 additions & 7 deletions src/vs/workbench/api/browser/mainThreadGitExtensionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,24 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { CancellationToken } from '../../../base/common/cancellation.js';
import { Disposable } from '../../../base/common/lifecycle.js';
import { URI } from '../../../base/common/uri.js';
import { IGitExtensionService, IGitService } from '../../contrib/git/common/gitService.js';
import { IGitExtensionDelegate, IGitService, GitRef, GitRefQuery, GitRefType } from '../../contrib/git/common/gitService.js';
import { extHostNamedCustomer, IExtHostContext } from '../../services/extensions/common/extHostCustomers.js';
import { ExtHostContext, ExtHostGitExtensionShape, MainContext, MainThreadGitExtensionShape } from '../common/extHost.protocol.js';
import { ExtHostContext, ExtHostGitExtensionShape, GitRefTypeDto, MainContext, MainThreadGitExtensionShape } from '../common/extHost.protocol.js';

function toGitRefType(type: GitRefTypeDto): GitRefType {
switch (type) {
case GitRefTypeDto.Head: return GitRefType.Head;
case GitRefTypeDto.RemoteHead: return GitRefType.RemoteHead;
case GitRefTypeDto.Tag: return GitRefType.Tag;
default: throw new Error(`Unknown GitRefType: ${type}`);
}
}

@extHostNamedCustomer(MainContext.MainThreadGitExtension)
export class MainThreadGitExtensionService extends Disposable implements MainThreadGitExtensionShape, IGitExtensionService {
export class MainThreadGitExtensionService extends Disposable implements MainThreadGitExtensionShape, IGitExtensionDelegate {
private readonly _proxy: ExtHostGitExtensionShape;

constructor(
Expand All @@ -20,16 +30,35 @@ export class MainThreadGitExtensionService extends Disposable implements MainThr
super();

this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostGitExtension);
gitService.setDelegate(this);
this._initializeDelegate();
}

private async _initializeDelegate(): Promise<void> {
// Check whether the vscode.git extension is available in the extension host
// process before setting the delegate. The delegate should only be set once,
// for the extension host process that runs the vscode.git extension
const isExtensionAvailable = await this._proxy.$isGitExtensionAvailable();

if (isExtensionAvailable && !this._store.isDisposed) {
this._register(this.gitService.setDelegate(this));
}
}

async openRepository(uri: URI): Promise<URI | undefined> {
const result = await this._proxy.$openRepository(uri);
return result ? URI.revive(result) : undefined;
}

override dispose(): void {
this.gitService.clearDelegate();
super.dispose();
async getRefs(root: URI, query: GitRefQuery, token?: CancellationToken): Promise<GitRef[]> {
const result = await this._proxy.$getRefs(root, query, token);

if (token?.isCancellationRequested) {
return [];
}

return result.map(ref => ({
...ref,
type: toGitRefType(ref.type)
} satisfies GitRef));
}
}
22 changes: 22 additions & 0 deletions src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3456,8 +3456,30 @@ export interface ExtHostChatSessionsShape {
$provideHandleOptionsChange(providerHandle: number, sessionResource: UriComponents, updates: ReadonlyArray<ChatSessionOptionUpdateDto>, token: CancellationToken): Promise<void>;
}

export interface GitRefQueryDto {
readonly contains?: string;
readonly count?: number;
readonly pattern?: string | string[];
readonly sort?: 'alphabetically' | 'committerdate' | 'creatordate';
}

export enum GitRefTypeDto {
Head,
RemoteHead,
Tag
}

export interface GitRefDto {
readonly id: string;
readonly name: string;
readonly type: GitRefTypeDto;
readonly revision: string;
}

export interface ExtHostGitExtensionShape {
$isGitExtensionAvailable(): Promise<boolean>;
$openRepository(root: UriComponents): Promise<UriComponents | undefined>;
$getRefs(root: UriComponents, query: GitRefQueryDto, token?: CancellationToken): Promise<GitRefDto[]>;
}

// --- proxy identifiers
Expand Down
81 changes: 77 additions & 4 deletions src/vs/workbench/api/common/extHostGitExtensionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,46 @@ import { ExtensionIdentifier } from '../../../platform/extensions/common/extensi
import { createDecorator } from '../../../platform/instantiation/common/instantiation.js';
import { IExtHostExtensionService } from './extHostExtensionService.js';
import { IExtHostRpcService } from './extHostRpcService.js';
import { ExtHostGitExtensionShape } from './extHost.protocol.js';
import { ExtHostGitExtensionShape, GitRefDto, GitRefQueryDto, GitRefTypeDto } from './extHost.protocol.js';

const GIT_EXTENSION_ID = 'vscode.git';

function toGitRefTypeDto(type: GitRefType): GitRefTypeDto {
switch (type) {
case GitRefType.Head: return GitRefTypeDto.Head;
case GitRefType.RemoteHead: return GitRefTypeDto.RemoteHead;
case GitRefType.Tag: return GitRefTypeDto.Tag;
default: throw new Error(`Unknown GitRefType: ${type}`);
}
}

interface Repository {
readonly rootUri: vscode.Uri;
getRefs(query: GitRefQuery, token?: vscode.CancellationToken): Promise<GitRef[]>;
}

interface GitRef {
type: GitRefType;
name?: string;
commit?: string;
remote?: string;
}

const enum GitRefType {
Head,
RemoteHead,
Tag
}

interface GitRefQuery {
readonly contains?: string;
readonly count?: number;
readonly pattern?: string | string[];
readonly sort?: 'alphabetically' | 'committerdate' | 'creatordate';
}

interface GitExtensionAPI {
openRepository(root: vscode.Uri): Promise<{ readonly rootUri: vscode.Uri } | null>;
openRepository(root: vscode.Uri): Promise<Repository | null>;
}

interface GitExtension {
Expand All @@ -41,7 +75,10 @@ export class ExtHostGitExtensionService extends Disposable implements IExtHostGi
super();
}

// --- Called by the main thread via RPC (ExtHostGitShape) ---
async $isGitExtensionAvailable(): Promise<boolean> {
const registry = await this._extHostExtensionService.getExtensionRegistry();
return !!registry.getExtensionDescription(GIT_EXTENSION_ID);
}

async $openRepository(uri: UriComponents): Promise<UriComponents | undefined> {
const api = await this._ensureGitApi();
Expand All @@ -53,7 +90,43 @@ export class ExtHostGitExtensionService extends Disposable implements IExtHostGi
return repository?.rootUri;
}

// --- Private helpers ---
async $getRefs(uri: UriComponents, query: GitRefQueryDto, token?: vscode.CancellationToken): Promise<GitRefDto[]> {
const api = await this._ensureGitApi();
if (!api) {
return [];
}

const repository = await api.openRepository(URI.revive(uri));
if (!repository) {
return [];
}

try {
const refs = await repository.getRefs(query, token);
const result: (GitRefDto | undefined)[] = refs.map(ref => {
if (!ref.name || !ref.commit) {
return undefined;
}

const id = ref.type === GitRefType.Head
? `refs/heads/${ref.name}`
: ref.type === GitRefType.RemoteHead
? `refs/remotes/${ref.remote}/${ref.name}`
: `refs/tags/${ref.name}`;

return {
id,
name: ref.name,
type: toGitRefTypeDto(ref.type),
revision: ref.commit
} satisfies GitRefDto;
});

return result.filter(ref => !!ref);
} catch {
return [];
}
}

private async _ensureGitApi(): Promise<GitExtensionAPI | undefined> {
if (this._gitApi) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,11 @@ abstract class SubmitAction extends Action2 {
}
}

const requestInProgressOrPendingToolCall = ContextKeyExpr.or(ChatContextKeys.requestInProgress, ChatContextKeys.Editing.hasToolConfirmation);
const requestInProgressOrPendingToolCall = ContextKeyExpr.or(
ChatContextKeys.requestInProgress,
ChatContextKeys.Editing.hasToolConfirmation,
ChatContextKeys.Editing.hasQuestionCarousel,
);
const whenNotInProgress = ChatContextKeys.requestInProgress.negate();

export class ChatSubmitAction extends SubmitAction {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1054,20 +1054,10 @@ export class ChatQuestionCarouselPart extends Disposable implements IChatContent
const freeformTextarea = this._freeformTextareas.get(question.id);
const freeformValue = freeformTextarea?.value !== '' ? freeformTextarea?.value : undefined;

// Only include defaults if nothing selected AND no freeform input
let finalSelectedValues = selectedValues;
if (selectedValues.length === 0 && !freeformValue && question.defaultValue !== undefined) {
const defaultIds = Array.isArray(question.defaultValue)
? question.defaultValue
: [question.defaultValue];
const defaultValues = question.options
?.filter(opt => defaultIds.includes(opt.id))
.map(opt => opt.value);
finalSelectedValues = defaultValues?.filter(v => v !== undefined) || [];
}

if (freeformValue || finalSelectedValues.length > 0) {
return { selectedValues: finalSelectedValues, freeformValue };
// Return whatever was selected - defaults are applied at render time when
// checkboxes are initially checked, so empty selection means user unchecked all
if (freeformValue || selectedValues.length > 0) {
return { selectedValues, freeformValue };
}
return undefined;
}
Expand Down
Loading
Loading