Skip to content

Commit 4949701

Browse files
authored
Add experiment to let us control the default mode/model for new chat sessions (#246150)
* Implement experiment for default mode and model * Simpler * Simplify, check experiments in the same place * Fixup * Fixes for safety * Add logs * Cleanup
1 parent a012671 commit 4949701

File tree

2 files changed

+69
-2
lines changed

2 files changed

+69
-2
lines changed

Diff for: src/vs/workbench/contrib/chat/browser/chatInputPart.ts

+57-1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ import { ITelemetryService } from '../../../../platform/telemetry/common/telemet
6666
import { IThemeService } from '../../../../platform/theme/common/themeService.js';
6767
import { ISharedWebContentExtractorService } from '../../../../platform/webContentExtractor/common/webContentExtractor.js';
6868
import { ResourceLabels } from '../../../browser/labels.js';
69+
import { IWorkbenchAssignmentService } from '../../../services/assignment/common/assignmentService.js';
6970
import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from '../../../services/editor/common/editorService.js';
7071
import { AccessibilityVerbositySettingId } from '../../accessibility/browser/accessibilityConfiguration.js';
7172
import { AccessibilityCommandId } from '../../accessibility/common/accessibilityCommands.js';
@@ -123,6 +124,7 @@ interface IChatInputPartOptions {
123124
renderWorkingSet?: boolean;
124125
enableImplicitContext?: boolean;
125126
supportsChangingModes?: boolean;
127+
widgetViewKindTag: string;
126128
}
127129

128130
export interface IWorkingSetEntry {
@@ -355,6 +357,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
355357
@IChatAgentService private readonly agentService: IChatAgentService,
356358
@IChatService private readonly chatService: IChatService,
357359
@ISharedWebContentExtractorService private readonly sharedWebExtracterService: ISharedWebContentExtractorService,
360+
@IWorkbenchAssignmentService private readonly experimentService: IWorkbenchAssignmentService,
358361
) {
359362
super();
360363

@@ -538,7 +541,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
538541
return localize('chatInput', "Chat Input");
539542
}
540543

541-
initForNewChatModel(state: IChatViewState): void {
544+
initForNewChatModel(state: IChatViewState, modelIsEmpty: boolean): void {
542545
this.history = this.loadHistory();
543546
this.history.add({
544547
text: state.inputValue ?? this.history.current().text,
@@ -556,6 +559,59 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
556559
} else if (this.location === ChatAgentLocation.EditingSession) {
557560
this.setChatMode(ChatMode.Edit);
558561
}
562+
563+
if (modelIsEmpty) {
564+
const storageKey = this.getDefaultModeExperimentStorageKey();
565+
const hasSetDefaultMode = this.storageService.getBoolean(storageKey, StorageScope.WORKSPACE, false);
566+
if (!hasSetDefaultMode) {
567+
Promise.all([
568+
this.experimentService.getTreatment('chat.defaultMode'),
569+
this.experimentService.getTreatment('chat.defaultLanguageModel'),
570+
]).then(([defaultModeTreatment, defaultLanguageModelTreatment]) => {
571+
if (typeof defaultModeTreatment === 'string') {
572+
this.storageService.store(storageKey, true, StorageScope.WORKSPACE, StorageTarget.MACHINE);
573+
const defaultMode = validateChatMode(defaultModeTreatment);
574+
if (defaultMode) {
575+
this.logService.trace(`Applying default mode from experiment: ${defaultMode}`);
576+
this.setChatMode(defaultMode);
577+
this.checkModelSupported();
578+
}
579+
}
580+
581+
if (typeof defaultLanguageModelTreatment === 'string' && this._currentMode === ChatMode.Agent) {
582+
this.storageService.store(storageKey, true, StorageScope.WORKSPACE, StorageTarget.MACHINE);
583+
this.logService.trace(`Applying default language model from experiment: ${defaultLanguageModelTreatment}`);
584+
this.setExpModelOrWait(defaultLanguageModelTreatment);
585+
}
586+
});
587+
}
588+
}
589+
}
590+
591+
private setExpModelOrWait(modelId: string) {
592+
const model = this.languageModelsService.lookupLanguageModel(modelId);
593+
if (model) {
594+
this.setCurrentLanguageModel({ metadata: model, identifier: modelId });
595+
this.checkModelSupported();
596+
this._waitForPersistedLanguageModel.clear();
597+
} else {
598+
this._waitForPersistedLanguageModel.value = this.languageModelsService.onDidChangeLanguageModels(e => {
599+
const model = e.added?.find(m => m.identifier === modelId);
600+
if (model) {
601+
this._waitForPersistedLanguageModel.clear();
602+
603+
if (model.metadata.isUserSelectable) {
604+
this.setCurrentLanguageModel({ metadata: model.metadata, identifier: modelId });
605+
this.checkModelSupported();
606+
}
607+
}
608+
});
609+
}
610+
}
611+
612+
private getDefaultModeExperimentStorageKey(): string {
613+
const tag = this.options.widgetViewKindTag;
614+
return `chat.${tag}.hasSetDefaultModeByExperiment`;
559615
}
560616

561617
logInputHistory(): void {

Diff for: src/vs/workbench/contrib/chat/browser/chatWidget.ts

+12-1
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,16 @@ export class ChatWidget extends Disposable implements IChatWidget {
836836
this._onDidChangeContentHeight.fire();
837837
}
838838

839+
private getWidgetViewKindTag(): string {
840+
if (!this.viewContext) {
841+
return 'editor';
842+
} else if ('viewId' in this.viewContext) {
843+
return 'view';
844+
} else {
845+
return 'quick';
846+
}
847+
}
848+
839849
private createInput(container: HTMLElement, options?: { renderFollowups: boolean; renderStyle?: 'compact' | 'minimal' }): void {
840850
this.inputPart = this._register(this.instantiationService.createInstance(ChatInputPart,
841851
this.location,
@@ -847,6 +857,7 @@ export class ChatWidget extends Disposable implements IChatWidget {
847857
enableImplicitContext: this.viewOptions.enableImplicitContext,
848858
renderWorkingSet: this.viewOptions.enableWorkingSet === 'explicit',
849859
supportsChangingModes: this.viewOptions.supportsChangingModes,
860+
widgetViewKindTag: this.getWidgetViewKindTag()
850861
},
851862
this.styles,
852863
() => this.collectInputState()
@@ -984,7 +995,7 @@ export class ChatWidget extends Disposable implements IChatWidget {
984995
this.viewModel = undefined;
985996
this.onDidChangeItems();
986997
}));
987-
this.inputPart.initForNewChatModel(viewState);
998+
this.inputPart.initForNewChatModel(viewState, model.getRequests().length === 0);
988999
this.contribs.forEach(c => {
9891000
if (c.setInputState && viewState.inputState?.[c.id]) {
9901001
c.setInputState(viewState.inputState?.[c.id]);

0 commit comments

Comments
 (0)