mirror of
https://github.com/microsoft/vscode.git
synced 2026-02-15 07:28:05 +00:00
Prototype agent sessions window (#289707)
* prototype agent sessions window * prototype agent sessions window * polish defaults * apply template changes on startup * move under resources * some fixes and disable profile actions in agent sessions window * disabe manage profile actions for agent sessions workspace * fix fixing window title * disable when chat is hidden * simplify * feedback * fix tests * disable the action in stable * Update resources/profiles/agent-sessions.code-profile Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/vs/platform/userDataProfile/common/userDataProfileTemplateWatcher.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/vs/platform/userDataProfile/common/userDataProfile.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Benjamin Pasero <benjamin.pasero@microsoft.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
4adf8989a8
commit
19209a8c1f
@@ -284,6 +284,8 @@ function packageTask(platform: string, arch: string, sourceFolderName: string, d
|
||||
|
||||
const telemetry = gulp.src('.build/telemetry/**', { base: '.build/telemetry', dot: true });
|
||||
|
||||
const profiles = gulp.src('resources/profiles/**', { base: '.', dot: true });
|
||||
|
||||
const jsFilter = util.filter(data => !data.isDirectory() && /\.js$/.test(data.path));
|
||||
const root = path.resolve(path.join(import.meta.dirname, '..'));
|
||||
const productionDependencies = getProductionDependencies(root);
|
||||
@@ -318,6 +320,7 @@ function packageTask(platform: string, arch: string, sourceFolderName: string, d
|
||||
license,
|
||||
api,
|
||||
telemetry,
|
||||
profiles,
|
||||
sources,
|
||||
deps
|
||||
);
|
||||
|
||||
19
resources/profiles/agent-sessions.code-profile
Normal file
19
resources/profiles/agent-sessions.code-profile
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "Agent Sessions",
|
||||
"icon": "copilot",
|
||||
"settings": {
|
||||
"workbench.statusBar.visible": false,
|
||||
"workbench.activityBar.location": "hidden",
|
||||
"workbench.sideBar.location": "right",
|
||||
"workbench.secondarySideBar.defaultVisibility": "maximized",
|
||||
"workbench.secondarySideBar.restoreMaximized": true,
|
||||
"chat.restoreLastPanelSession": true,
|
||||
"workbench.startupEditor": "none",
|
||||
"workbench.editor.restoreEditors": false,
|
||||
"chat.agentsControl.enabled": true,
|
||||
"files.autoSave": "afterDelay",
|
||||
"chat.commandCenter.enabled": false,
|
||||
"window.title": "Agent Sessions",
|
||||
"workbench.editor.showTabs": "single"
|
||||
}
|
||||
}
|
||||
@@ -132,6 +132,7 @@ import { McpManagementChannel } from '../../../platform/mcp/common/mcpManagement
|
||||
import { AllowedMcpServersService } from '../../../platform/mcp/common/allowedMcpServersService.js';
|
||||
import { IMcpGalleryManifestService } from '../../../platform/mcp/common/mcpGalleryManifest.js';
|
||||
import { McpGalleryManifestIPCService } from '../../../platform/mcp/common/mcpGalleryManifestServiceIpc.js';
|
||||
import { UserDataProfileTemplatesWatcher } from '../../../platform/userDataProfile/common/userDataProfileTemplateWatcher.js';
|
||||
|
||||
class SharedProcessMain extends Disposable implements IClientConnectionFilter {
|
||||
|
||||
@@ -197,7 +198,8 @@ class SharedProcessMain extends Disposable implements IClientConnectionFilter {
|
||||
instantiationService.createInstance(LocalizationsUpdater),
|
||||
instantiationService.createInstance(ExtensionsContributions),
|
||||
instantiationService.createInstance(UserDataProfilesCleaner),
|
||||
instantiationService.createInstance(DefaultExtensionsInitializer)
|
||||
instantiationService.createInstance(DefaultExtensionsInitializer),
|
||||
instantiationService.createInstance(UserDataProfileTemplatesWatcher)
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -220,6 +220,7 @@ class StandaloneEnvironmentService implements IEnvironmentService {
|
||||
readonly keyboardLayoutResource: URI = URI.from({ scheme: 'monaco', authority: 'keyboardLayoutResource' });
|
||||
readonly argvResource: URI = URI.from({ scheme: 'monaco', authority: 'argvResource' });
|
||||
readonly untitledWorkspacesHome: URI = URI.from({ scheme: 'monaco', authority: 'untitledWorkspacesHome' });
|
||||
readonly builtinProfilesHome: URI = URI.from({ scheme: 'monaco', authority: 'builtinProfilesHome' });
|
||||
readonly workspaceStorageHome: URI = URI.from({ scheme: 'monaco', authority: 'workspaceStorageHome' });
|
||||
readonly localHistoryHome: URI = URI.from({ scheme: 'monaco', authority: 'localHistoryHome' });
|
||||
readonly cacheHome: URI = URI.from({ scheme: 'monaco', authority: 'cacheHome' });
|
||||
|
||||
@@ -58,6 +58,7 @@ export interface IEnvironmentService {
|
||||
workspaceStorageHome: URI;
|
||||
localHistoryHome: URI;
|
||||
cacheHome: URI;
|
||||
builtinProfilesHome: URI;
|
||||
|
||||
// --- settings sync
|
||||
userDataSyncHome: URI;
|
||||
@@ -88,6 +89,9 @@ export interface IEnvironmentService {
|
||||
disableExperiments: boolean;
|
||||
serviceMachineIdResource: URI;
|
||||
|
||||
// --- agent sessions workspace
|
||||
agentSessionsWorkspace?: URI;
|
||||
|
||||
// --- Policy
|
||||
policyFile?: URI;
|
||||
|
||||
|
||||
@@ -107,6 +107,9 @@ export abstract class AbstractNativeEnvironmentService implements INativeEnviron
|
||||
@memoize
|
||||
get untitledWorkspacesHome(): URI { return URI.file(join(this.userDataPath, 'Workspaces')); }
|
||||
|
||||
@memoize
|
||||
get builtinProfilesHome(): URI { return joinPath(URI.file(this.appRoot), 'resources', 'profiles'); }
|
||||
|
||||
@memoize
|
||||
get builtinExtensionsPath(): string {
|
||||
const cliBuiltinExtensionsDir = this.args['builtin-extensions-dir'];
|
||||
@@ -117,6 +120,7 @@ export abstract class AbstractNativeEnvironmentService implements INativeEnviron
|
||||
return normalize(join(FileAccess.asFileUri('').fsPath, '..', 'extensions'));
|
||||
}
|
||||
|
||||
@memoize
|
||||
get extensionsDownloadLocation(): URI {
|
||||
const cliExtensionsDownloadDir = this.args['extensions-download-dir'];
|
||||
if (cliExtensionsDownloadDir) {
|
||||
@@ -252,6 +256,11 @@ export abstract class AbstractNativeEnvironmentService implements INativeEnviron
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@memoize
|
||||
get agentSessionsWorkspace(): URI {
|
||||
return joinPath(this.appSettingsHome, 'agent-sessions.code-workspace');
|
||||
}
|
||||
|
||||
get editSessionId(): string | undefined { return this.args['editSessionId']; }
|
||||
|
||||
get exportPolicyData(): string | undefined {
|
||||
|
||||
@@ -20,6 +20,8 @@ import { Promises } from '../../../base/common/async.js';
|
||||
import { generateUuid } from '../../../base/common/uuid.js';
|
||||
import { escapeRegExpCharacters } from '../../../base/common/strings.js';
|
||||
import { isString, Mutable } from '../../../base/common/types.js';
|
||||
import { ResourceMap } from '../../../base/common/map.js';
|
||||
import { parse } from '../../../base/common/json.js';
|
||||
|
||||
export const enum ProfileResourceType {
|
||||
Settings = 'settings',
|
||||
@@ -37,6 +39,14 @@ export const enum ProfileResourceType {
|
||||
*/
|
||||
export type UseDefaultProfileFlags = { [key in ProfileResourceType]?: boolean };
|
||||
export type ProfileResourceTypeFlags = UseDefaultProfileFlags;
|
||||
export type SettingValue = string | boolean | number | undefined | null | object;
|
||||
export type ISettingsDictionary = Record<string, SettingValue>;
|
||||
|
||||
export interface ITemplateData {
|
||||
readonly resource: URI;
|
||||
readonly icon?: string;
|
||||
readonly settings?: ISettingsDictionary;
|
||||
}
|
||||
|
||||
export interface IUserDataProfile {
|
||||
readonly id: string;
|
||||
@@ -56,6 +66,7 @@ export interface IUserDataProfile {
|
||||
readonly useDefaultFlags?: UseDefaultProfileFlags;
|
||||
readonly isTransient?: boolean;
|
||||
readonly workspaces?: readonly URI[];
|
||||
readonly templateData?: ITemplateData;
|
||||
}
|
||||
|
||||
export function isUserDataProfile(thing: unknown): thing is IUserDataProfile {
|
||||
@@ -77,6 +88,13 @@ export function isUserDataProfile(thing: unknown): thing is IUserDataProfile {
|
||||
);
|
||||
}
|
||||
|
||||
export interface ISystemProfileTemplate {
|
||||
readonly name: string;
|
||||
readonly icon?: string;
|
||||
readonly settings?: ISettingsDictionary;
|
||||
readonly globalState?: IStringDictionary<string>;
|
||||
}
|
||||
|
||||
export type DidChangeProfilesEvent = { readonly added: readonly IUserDataProfile[]; readonly removed: readonly IUserDataProfile[]; readonly updated: readonly IUserDataProfile[]; readonly all: readonly IUserDataProfile[] };
|
||||
|
||||
export type WillCreateProfileEvent = {
|
||||
@@ -94,9 +112,10 @@ export interface IUserDataProfileOptions {
|
||||
readonly useDefaultFlags?: UseDefaultProfileFlags;
|
||||
readonly transient?: boolean;
|
||||
readonly workspaces?: readonly URI[];
|
||||
readonly templateData?: ITemplateData;
|
||||
}
|
||||
|
||||
export interface IUserDataProfileUpdateOptions extends Omit<IUserDataProfileOptions, 'icon'> {
|
||||
export interface IUserDataProfileUpdateOptions extends Omit<IUserDataProfileOptions, 'icon' | 'defaultSettings'> {
|
||||
readonly name?: string;
|
||||
readonly icon?: string | null;
|
||||
}
|
||||
@@ -113,6 +132,7 @@ export interface IUserDataProfilesService {
|
||||
|
||||
readonly onDidResetWorkspaces: Event<void>;
|
||||
|
||||
createSystemProfile(id: string): Promise<IUserDataProfile>;
|
||||
createNamedProfile(name: string, options?: IUserDataProfileOptions, workspaceIdentifier?: IAnyWorkspaceIdentifier): Promise<IUserDataProfile>;
|
||||
createTransientProfile(workspaceIdentifier?: IAnyWorkspaceIdentifier): Promise<IUserDataProfile>;
|
||||
createProfile(id: string, name: string, options?: IUserDataProfileOptions, workspaceIdentifier?: IAnyWorkspaceIdentifier): Promise<IUserDataProfile>;
|
||||
@@ -145,6 +165,10 @@ export function reviveProfile(profile: UriDto<IUserDataProfile>, scheme: string)
|
||||
useDefaultFlags: profile.useDefaultFlags,
|
||||
isTransient: profile.isTransient,
|
||||
workspaces: profile.workspaces?.map(w => URI.revive(w)),
|
||||
templateData: profile.templateData ? {
|
||||
...profile.templateData,
|
||||
resource: URI.revive(profile.templateData?.resource),
|
||||
} : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -167,6 +191,7 @@ export function toUserDataProfile(id: string, name: string, location: URI, profi
|
||||
useDefaultFlags: options?.useDefaultFlags,
|
||||
isTransient: options?.transient,
|
||||
workspaces: options?.workspaces,
|
||||
templateData: options?.templateData,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -180,6 +205,7 @@ export type StoredUserDataProfile = {
|
||||
location: URI;
|
||||
icon?: string;
|
||||
useDefaultFlags?: UseDefaultProfileFlags;
|
||||
templateData?: ITemplateData;
|
||||
};
|
||||
|
||||
export type StoredProfileAssociations = {
|
||||
@@ -245,7 +271,7 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
|
||||
this.logService.warn('Skipping the invalid stored profile', storedProfile.location || storedProfile.name);
|
||||
continue;
|
||||
}
|
||||
profiles.push(toUserDataProfile(basename(storedProfile.location), storedProfile.name, storedProfile.location, this.profilesCacheHome, { icon: storedProfile.icon, useDefaultFlags: storedProfile.useDefaultFlags }, defaultProfile));
|
||||
profiles.push(toUserDataProfile(basename(storedProfile.location), storedProfile.name, storedProfile.location, this.profilesCacheHome, { icon: storedProfile.icon, useDefaultFlags: storedProfile.useDefaultFlags, templateData: storedProfile.templateData }, defaultProfile));
|
||||
}
|
||||
} catch (error) {
|
||||
this.logService.error(error);
|
||||
@@ -310,6 +336,20 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
|
||||
return profile;
|
||||
}
|
||||
|
||||
async createSystemProfile(id: string): Promise<IUserDataProfile> {
|
||||
const existing = this.profiles.find(p => p.id === id);
|
||||
if (existing) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
const systemProfileTemplate = await this.getSystemProfileTemplate(id);
|
||||
if (!systemProfileTemplate) {
|
||||
throw new Error(`System profile template '${id}' does not exist`);
|
||||
}
|
||||
|
||||
return this.doCreateProfile(id, systemProfileTemplate.name);
|
||||
}
|
||||
|
||||
private async doCreateProfile(id: string, name: string, options?: IUserDataProfileOptions, workspaceIdentifier?: IAnyWorkspaceIdentifier): Promise<IUserDataProfile> {
|
||||
if (!isString(name) || !name) {
|
||||
throw new Error('Name of the profile is mandatory and must be of type `string`');
|
||||
@@ -328,6 +368,20 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
|
||||
if (URI.isUri(workspace)) {
|
||||
options = { ...options, workspaces: [workspace] };
|
||||
}
|
||||
|
||||
const systemProfileTemplate = await this.getSystemProfileTemplate(id);
|
||||
if (systemProfileTemplate) {
|
||||
options = {
|
||||
...options,
|
||||
icon: options?.icon ?? systemProfileTemplate.icon,
|
||||
templateData: {
|
||||
resource: joinPath(this.environmentService.builtinProfilesHome, `${id}.code-profile`),
|
||||
icon: systemProfileTemplate.icon,
|
||||
settings: systemProfileTemplate.settings,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const profile = toUserDataProfile(id, name, joinPath(this.profilesHome, id), this.profilesCacheHome, options, this.defaultProfile);
|
||||
await this.fileService.createFolder(profile.location);
|
||||
|
||||
@@ -366,6 +420,10 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
|
||||
transient: options.transient ?? existing.isTransient,
|
||||
useDefaultFlags: options.useDefaultFlags ?? existing.useDefaultFlags,
|
||||
workspaces: options.workspaces ?? existing.workspaces,
|
||||
templateData: existing.templateData ? {
|
||||
...existing.templateData,
|
||||
...options.templateData,
|
||||
} : undefined,
|
||||
}, this.defaultProfile);
|
||||
} else if (options.workspaces) {
|
||||
profileToUpdate = existing;
|
||||
@@ -500,6 +558,50 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
|
||||
: (this.profilesObject.emptyWindows.get(workspace) ?? this.transientProfilesObject.emptyWindows.get(workspace));
|
||||
}
|
||||
|
||||
private getSystemProfileTemplate(id: string): Promise<ISystemProfileTemplate | undefined> {
|
||||
return this.getSystemProfileTemplates().then(templates => {
|
||||
const resource = joinPath(this.environmentService.builtinProfilesHome, `${id}.code-profile`);
|
||||
return templates.get(resource);
|
||||
});
|
||||
}
|
||||
|
||||
private systemProfilesTemplatesPromise: Promise<ResourceMap<ISystemProfileTemplate>> | undefined;
|
||||
private async getSystemProfileTemplates(): Promise<ResourceMap<ISystemProfileTemplate>> {
|
||||
if (!this.systemProfilesTemplatesPromise) {
|
||||
this.systemProfilesTemplatesPromise = this.doGetSystemProfileTemplates();
|
||||
}
|
||||
return this.systemProfilesTemplatesPromise;
|
||||
}
|
||||
|
||||
private async doGetSystemProfileTemplates(): Promise<ResourceMap<ISystemProfileTemplate>> {
|
||||
const result = new ResourceMap<ISystemProfileTemplate>();
|
||||
const profilesFolder = this.environmentService.builtinProfilesHome;
|
||||
try {
|
||||
const stat = await this.fileService.resolve(profilesFolder);
|
||||
if (!stat.children?.length) {
|
||||
return result;
|
||||
}
|
||||
for (const child of stat.children) {
|
||||
if (child.isDirectory) {
|
||||
continue;
|
||||
}
|
||||
if (this.uriIdentityService.extUri.extname(child.resource) !== '.code-profile') {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
const content = (await this.fileService.readFile(child.resource)).value.toString();
|
||||
const profile: ISystemProfileTemplate = parse(content);
|
||||
result.set(child.resource, profile);
|
||||
} catch (error) {
|
||||
this.logService.error(`Error while reading system profile template from ${child.resource.toString()}`, error);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
this.logService.error(`Error while reading system profile templates from ${profilesFolder.toString()}`, error);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected getWorkspace(workspaceIdentifier: IAnyWorkspaceIdentifier): URI | string {
|
||||
if (isSingleFolderWorkspaceIdentifier(workspaceIdentifier)) {
|
||||
return workspaceIdentifier.uri;
|
||||
@@ -609,7 +711,7 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
|
||||
continue;
|
||||
}
|
||||
if (!profile.isDefault) {
|
||||
storedProfiles.push({ location: profile.location, name: profile.name, icon: profile.icon, useDefaultFlags: profile.useDefaultFlags });
|
||||
storedProfiles.push({ location: profile.location, name: profile.name, icon: profile.icon, useDefaultFlags: profile.useDefaultFlags, templateData: profile.templateData });
|
||||
}
|
||||
if (profile.workspaces) {
|
||||
for (const workspace of profile.workspaces) {
|
||||
|
||||
@@ -94,6 +94,11 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
|
||||
return reviveProfile(result, this.profilesHome.scheme);
|
||||
}
|
||||
|
||||
async createSystemProfile(id: string): Promise<IUserDataProfile> {
|
||||
const result = await this.channel.call<UriDto<IUserDataProfile>>('createSystemProfile', [id]);
|
||||
return reviveProfile(result, this.profilesHome.scheme);
|
||||
}
|
||||
|
||||
async createTransientProfile(workspaceIdentifier?: IAnyWorkspaceIdentifier): Promise<IUserDataProfile> {
|
||||
const result = await this.channel.call<UriDto<IUserDataProfile>>('createTransientProfile', [workspaceIdentifier]);
|
||||
return reviveProfile(result, this.profilesHome.scheme);
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable, DisposableMap, IDisposable } from '../../../base/common/lifecycle.js';
|
||||
import { IFileService } from '../../files/common/files.js';
|
||||
import { ILogService } from '../../log/common/log.js';
|
||||
import { IUserDataProfile, IUserDataProfilesService, IUserDataProfileUpdateOptions, ISystemProfileTemplate } from './userDataProfile.js';
|
||||
import { isEmptyObject, Mutable } from '../../../base/common/types.js';
|
||||
import { equals } from '../../../base/common/objects.js';
|
||||
|
||||
export class UserDataProfileTemplatesWatcher extends Disposable {
|
||||
|
||||
private readonly templateWatchers = this._register(new DisposableMap<string, IDisposable>());
|
||||
|
||||
constructor(
|
||||
@IUserDataProfilesService private readonly userDataProfilesService: IUserDataProfilesService,
|
||||
@IFileService private readonly fileService: IFileService,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
) {
|
||||
super();
|
||||
|
||||
// Watch template files for existing profiles
|
||||
for (const profile of this.userDataProfilesService.profiles) {
|
||||
this.watchProfileTemplate(profile);
|
||||
}
|
||||
|
||||
// Listen for profile changes to update watchers
|
||||
this._register(this.userDataProfilesService.onDidChangeProfiles(e => {
|
||||
// Stop watching removed profiles
|
||||
for (const profile of e.removed) {
|
||||
this.unwatchProfileTemplate(profile);
|
||||
}
|
||||
|
||||
// Start watching added profiles
|
||||
for (const profile of e.added) {
|
||||
this.watchProfileTemplate(profile);
|
||||
}
|
||||
|
||||
// Update watchers for updated profiles (templateResource might have changed)
|
||||
for (const profile of e.updated) {
|
||||
this.unwatchProfileTemplate(profile);
|
||||
this.watchProfileTemplate(profile);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private async watchProfileTemplate(profile: IUserDataProfile): Promise<void> {
|
||||
const templateResource = profile.templateData?.resource;
|
||||
|
||||
if (!templateResource) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await this.onDidChangeProfileTemplate(profile); // Apply any changes on startup
|
||||
} catch (error) {
|
||||
this.logService.error(`UserDataProfileTemplateService: Failed to apply template changes on startup for profile '${profile.name}'`, error);
|
||||
}
|
||||
|
||||
this.logService.trace(`UserDataProfileTemplateService: Watching template file for profile '${profile.name}'`, templateResource.toString());
|
||||
const watcher = this.fileService.createWatcher(templateResource, { recursive: false, excludes: [] });
|
||||
const disposable = watcher.onDidChange(async () => {
|
||||
this.logService.trace(`UserDataProfileTemplateService: Template file changed for profile '${profile.name}'`, templateResource.toString());
|
||||
// Get the latest profile in case it was updated
|
||||
const currentProfile = this.userDataProfilesService.profiles.find(p => p.id === profile.id);
|
||||
if (currentProfile) {
|
||||
try {
|
||||
await this.onDidChangeProfileTemplate(currentProfile);
|
||||
} catch (error) {
|
||||
this.logService.error(`UserDataProfileTemplateService: Failed to apply template changes when template file changed for profile '${profile.name}'`, error);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.templateWatchers.set(profile.id, {
|
||||
dispose: () => {
|
||||
disposable.dispose();
|
||||
watcher.dispose();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private unwatchProfileTemplate(profile: IUserDataProfile): void {
|
||||
this.templateWatchers.deleteAndDispose(profile.id);
|
||||
}
|
||||
|
||||
private async onDidChangeProfileTemplate(profile: IUserDataProfile): Promise<void> {
|
||||
if (!profile.templateData?.resource) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.logService.info(`UserDataProfileTemplateService: Template file changed for profile '${profile.name}', checking for changes...`);
|
||||
|
||||
try {
|
||||
const sourceTemplate = await this.resolveSourceTemplate(profile);
|
||||
|
||||
if (!sourceTemplate) {
|
||||
this.logService.warn(`UserDataProfileTemplateService: Could not resolve source template for profile '${profile.name}'`);
|
||||
return;
|
||||
}
|
||||
|
||||
const profileUpdateOptions: Mutable<IUserDataProfileUpdateOptions> = Object.create(null);
|
||||
|
||||
if (sourceTemplate.icon !== profile.templateData?.icon && profile.templateData?.icon === profile.icon) {
|
||||
profileUpdateOptions.icon = sourceTemplate.icon;
|
||||
}
|
||||
|
||||
if (!equals(sourceTemplate.settings, profile.templateData.settings)) {
|
||||
this.logService.trace(`UserDataProfileTemplateService: Updating default settings for profile '${profile.name}'`);
|
||||
profileUpdateOptions.templateData = { ...profile.templateData, settings: sourceTemplate.settings };
|
||||
}
|
||||
|
||||
if (!isEmptyObject(profileUpdateOptions)) {
|
||||
await this.userDataProfilesService.updateProfile(profile, profileUpdateOptions);
|
||||
}
|
||||
|
||||
this.logService.info(`UserDataProfileTemplateService: Successfully applied template changes to profile '${profile.name}'`);
|
||||
} catch (error) {
|
||||
this.logService.error(`UserDataProfileTemplateService: Failed to apply template changes to profile '${profile.name}'`, error);
|
||||
}
|
||||
}
|
||||
|
||||
private async resolveSourceTemplate(profile: IUserDataProfile): Promise<ISystemProfileTemplate | null> {
|
||||
if (!profile.templateData?.resource) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const content = await this.fileService.readFile(profile.templateData.resource);
|
||||
return JSON.parse(content.value.toString());
|
||||
} catch (error) {
|
||||
this.logService.error(`UserDataProfileTemplateService: Failed to resolve source template for profile '${profile.name}'`, error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,11 @@ export class UserDataProfilesReadonlyService extends BaseUserDataProfilesService
|
||||
|
||||
protected override getStoredProfiles(): StoredUserDataProfile[] {
|
||||
const storedProfilesState = this.stateReadonlyService.getItem<UriDto<StoredUserDataProfileState>[]>(UserDataProfilesReadonlyService.PROFILES_KEY, []);
|
||||
return storedProfilesState.map(p => ({ ...p, location: isString(p.location) ? this.uriIdentityService.extUri.joinPath(this.profilesHome, p.location) : URI.revive(p.location) }));
|
||||
return storedProfilesState.map(p => ({
|
||||
...p,
|
||||
location: isString(p.location) ? this.uriIdentityService.extUri.joinPath(this.profilesHome, p.location) : URI.revive(p.location),
|
||||
templateData: p.templateData ? { ...p.templateData, resource: URI.revive(p.templateData.resource) } : undefined
|
||||
}));
|
||||
}
|
||||
|
||||
protected override getStoredProfileAssociations(): StoredProfileAssociations {
|
||||
|
||||
@@ -68,6 +68,7 @@ export class UserDataSyncClient extends Disposable {
|
||||
cacheHome: joinPath(userRoamingDataHome, 'cache'),
|
||||
argvResource: joinPath(userRoamingDataHome, 'argv.json'),
|
||||
sync: 'on',
|
||||
builtinProfilesHome: joinPath(userRoamingDataHome, 'builtinProfiles')
|
||||
});
|
||||
|
||||
this.instantiationService.stub(IProductService, {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { Disposable } from '../../base/common/lifecycle.js';
|
||||
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from '../../platform/contextkey/common/contextkey.js';
|
||||
import { IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from '../../platform/contextkey/common/contextkeys.js';
|
||||
import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext } from '../common/contextkeys.js';
|
||||
import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsAgentSessionsWorkspaceContext } from '../common/contextkeys.js';
|
||||
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from '../services/editor/common/editorGroupsService.js';
|
||||
import { IConfigurationService } from '../../platform/configuration/common/configuration.js';
|
||||
import { IWorkbenchEnvironmentService } from '../services/environment/common/environmentService.js';
|
||||
@@ -47,6 +47,7 @@ export class WorkbenchContextKeysHandler extends Disposable {
|
||||
|
||||
private virtualWorkspaceContext: IContextKey<string>;
|
||||
private temporaryWorkspaceContext: IContextKey<boolean>;
|
||||
private isAgentSessionsWorkspaceContext: IContextKey<boolean>;
|
||||
private inAutomationContext: IContextKey<boolean>;
|
||||
|
||||
private inZenModeContext: IContextKey<boolean>;
|
||||
@@ -93,6 +94,8 @@ export class WorkbenchContextKeysHandler extends Disposable {
|
||||
|
||||
this.virtualWorkspaceContext = VirtualWorkspaceContext.bindTo(this.contextKeyService);
|
||||
this.temporaryWorkspaceContext = TemporaryWorkspaceContext.bindTo(this.contextKeyService);
|
||||
this.isAgentSessionsWorkspaceContext = IsAgentSessionsWorkspaceContext.bindTo(this.contextKeyService);
|
||||
this.isAgentSessionsWorkspaceContext.set(!!this.environmentService.agentSessionsWindow);
|
||||
this.updateWorkspaceContextKeys();
|
||||
|
||||
// Capabilities
|
||||
|
||||
@@ -821,7 +821,7 @@ export class BrowserTitlebarPart extends Part implements ITitlebarPart {
|
||||
|
||||
private get activityActionsEnabled(): boolean {
|
||||
const activityBarPosition = this.configurationService.getValue<ActivityBarPosition>(LayoutSettings.ACTIVITY_BAR_LOCATION);
|
||||
return !this.isCompact && !this.isAuxiliary && (activityBarPosition === ActivityBarPosition.TOP || activityBarPosition === ActivityBarPosition.BOTTOM);
|
||||
return !this.isCompact && !this.isAuxiliary && (activityBarPosition === ActivityBarPosition.TOP || activityBarPosition === ActivityBarPosition.BOTTOM || activityBarPosition === ActivityBarPosition.HIDDEN);
|
||||
}
|
||||
|
||||
private get globalActionsEnabled(): boolean {
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
import { localize } from '../../../../nls.js';
|
||||
import { dirname, basename } from '../../../../base/common/resources.js';
|
||||
import { ITitleProperties, ITitleVariable } from './titlebarPart.js';
|
||||
import { IConfigurationService, IConfigurationChangeEvent } from '../../../../platform/configuration/common/configuration.js';
|
||||
import { IConfigurationService, IConfigurationChangeEvent, isConfigured } from '../../../../platform/configuration/common/configuration.js';
|
||||
import { Extensions as ConfigurationExtensions, IConfigurationRegistry } from '../../../../platform/configuration/common/configurationRegistry.js';
|
||||
import { Registry } from '../../../../platform/registry/common/platform.js';
|
||||
import { IEditorService } from '../../../services/editor/common/editorService.js';
|
||||
import { Disposable, DisposableStore } from '../../../../base/common/lifecycle.js';
|
||||
import { EditorResourceAccessor, Verbosity, SideBySideEditor } from '../../../common/editor.js';
|
||||
@@ -412,6 +414,13 @@ export class WindowTitle extends Disposable {
|
||||
const title = this.configurationService.inspect<string>(WindowSettingNames.title);
|
||||
const titleSeparator = this.configurationService.inspect<string>(WindowSettingNames.titleSeparator);
|
||||
|
||||
return title.value !== title.defaultValue || titleSeparator.value !== titleSeparator.defaultValue;
|
||||
if (isConfigured(title) || isConfigured(titleSeparator)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if the default value is overridden from the configuration registry
|
||||
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
|
||||
const configurationProperties = configurationRegistry.getConfigurationProperties();
|
||||
return title.defaultValue !== configurationProperties[WindowSettingNames.title]?.defaultDefaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ export const RemoteNameContext = new RawContextKey<string>('remoteName', '', loc
|
||||
export const VirtualWorkspaceContext = new RawContextKey<string>('virtualWorkspace', '', localize('virtualWorkspace', "The scheme of the current workspace is from a virtual file system or an empty string."));
|
||||
export const TemporaryWorkspaceContext = new RawContextKey<boolean>('temporaryWorkspace', false, localize('temporaryWorkspace', "The scheme of the current workspace is from a temporary file system."));
|
||||
|
||||
export const IsAgentSessionsWorkspaceContext = new RawContextKey<boolean>('isAgentSessionsWorkspace', false, localize('isAgentSessionsWorkspace', "Whether the current workspace is the agent sessions workspace."));
|
||||
|
||||
export const HasWebFileSystemAccess = new RawContextKey<boolean>('hasWebFileSystemAccess', false, true); // Support for FileSystemAccess web APIs (https://wicg.github.io/file-system-access)
|
||||
|
||||
export const EmbedderIdentifierContext = new RawContextKey<string | undefined>('embedderIdentifier', undefined, localize('embedderIdentifier', 'The identifier of the embedder according to the product service, if one is defined'));
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { VSBuffer } from '../../../../../base/common/buffer.js';
|
||||
import { ServicesAccessor } from '../../../../../editor/browser/editorExtensions.js';
|
||||
import { localize2 } from '../../../../../nls.js';
|
||||
import { Action2 } from '../../../../../platform/actions/common/actions.js';
|
||||
import { ContextKeyExpr } from '../../../../../platform/contextkey/common/contextkey.js';
|
||||
import { ProductQualityContext } from '../../../../../platform/contextkey/common/contextkeys.js';
|
||||
import { INativeEnvironmentService } from '../../../../../platform/environment/common/environment.js';
|
||||
import { IFileService } from '../../../../../platform/files/common/files.js';
|
||||
import { INativeHostService } from '../../../../../platform/native/common/native.js';
|
||||
import { IUserDataProfilesService } from '../../../../../platform/userDataProfile/common/userDataProfile.js';
|
||||
import { ChatEntitlementContextKeys } from '../../../../services/chat/common/chatEntitlementService.js';
|
||||
import { CHAT_CATEGORY } from '../../browser/actions/chatActions.js';
|
||||
|
||||
export class OpenAgentSessionsWindowAction extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'workbench.action.openAgentSessionsWindow',
|
||||
title: localize2('openAgentSessionsWindow', "Open Agent Sessions Window"),
|
||||
category: CHAT_CATEGORY,
|
||||
precondition: ContextKeyExpr.and(ChatEntitlementContextKeys.Setup.hidden.negate(), ProductQualityContext.notEqualsTo('stable')),
|
||||
f1: true,
|
||||
});
|
||||
}
|
||||
|
||||
async run(accessor: ServicesAccessor) {
|
||||
const environmentService = accessor.get(INativeEnvironmentService);
|
||||
const nativeHostService = accessor.get(INativeHostService);
|
||||
const userDataProfilesService = accessor.get(IUserDataProfilesService);
|
||||
const fileService = accessor.get(IFileService);
|
||||
|
||||
// Create workspace file if it doesn't exist
|
||||
const workspaceUri = environmentService.agentSessionsWorkspace;
|
||||
if (!workspaceUri) {
|
||||
throw new Error('Agent Sessions workspace is not configured');
|
||||
}
|
||||
|
||||
const workspaceExists = await fileService.exists(workspaceUri);
|
||||
if (!workspaceExists) {
|
||||
const emptyWorkspaceContent = JSON.stringify({ folders: [] }, null, '\t');
|
||||
await fileService.writeFile(workspaceUri, VSBuffer.fromString(emptyWorkspaceContent));
|
||||
}
|
||||
|
||||
const profile = await userDataProfilesService.createSystemProfile('agent-sessions');
|
||||
await userDataProfilesService.updateProfile(profile, { workspaces: [workspaceUri] });
|
||||
await nativeHostService.openWindow([{ workspaceUri }], { forceNewWindow: true });
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ import { registerChatDeveloperActions } from './actions/chatDeveloperActions.js'
|
||||
import { registerChatExportZipAction } from './actions/chatExportZip.js';
|
||||
import { HoldToVoiceChatInChatViewAction, InlineVoiceChatAction, KeywordActivationContribution, QuickVoiceChatAction, ReadChatResponseAloud, StartVoiceChatAction, StopListeningAction, StopListeningAndSubmitAction, StopReadAloud, StopReadChatItemAloud, VoiceChatInChatViewAction } from './actions/voiceChatActions.js';
|
||||
import { NativeBuiltinToolsContribution } from './builtInTools/tools.js';
|
||||
import { OpenAgentSessionsWindowAction } from './actions/agentSessionsActions.js';
|
||||
|
||||
class ChatCommandLineHandler extends Disposable {
|
||||
|
||||
@@ -180,6 +181,7 @@ class ChatLifecycleHandler extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
registerAction2(OpenAgentSessionsWindowAction);
|
||||
registerAction2(StartVoiceChatAction);
|
||||
|
||||
registerAction2(VoiceChatInChatViewAction);
|
||||
|
||||
@@ -58,7 +58,7 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@ILifecycleService private readonly lifecycleService: ILifecycleService,
|
||||
@IURLService private readonly urlService: IURLService,
|
||||
@IBrowserWorkbenchEnvironmentService environmentService: IBrowserWorkbenchEnvironmentService
|
||||
@IBrowserWorkbenchEnvironmentService private readonly environmentService: IBrowserWorkbenchEnvironmentService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -76,22 +76,25 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
|
||||
this.hasProfilesContext.set(this.userDataProfilesService.profiles.length > 1);
|
||||
this._register(this.userDataProfilesService.onDidChangeProfiles(e => this.hasProfilesContext.set(this.userDataProfilesService.profiles.length > 1)));
|
||||
|
||||
this.registerEditor();
|
||||
this.registerActions();
|
||||
if (!this.environmentService.agentSessionsWindow) {
|
||||
|
||||
this._register(this.urlService.registerHandler(this));
|
||||
this.registerEditor();
|
||||
this.registerActions();
|
||||
|
||||
if (isWeb) {
|
||||
lifecycleService.when(LifecyclePhase.Eventually).then(() => userDataProfilesService.cleanUp());
|
||||
this._register(this.urlService.registerHandler(this));
|
||||
|
||||
if (isWeb) {
|
||||
lifecycleService.when(LifecyclePhase.Eventually).then(() => userDataProfilesService.cleanUp());
|
||||
}
|
||||
|
||||
this.reportWorkspaceProfileInfo();
|
||||
|
||||
if (environmentService.options?.profileToPreview) {
|
||||
lifecycleService.when(LifecyclePhase.Restored).then(() => this.handleURL(URI.revive(environmentService.options!.profileToPreview!)));
|
||||
}
|
||||
|
||||
this.registerDropHandler();
|
||||
}
|
||||
|
||||
this.reportWorkspaceProfileInfo();
|
||||
|
||||
if (environmentService.options?.profileToPreview) {
|
||||
lifecycleService.when(LifecyclePhase.Restored).then(() => this.handleURL(URI.revive(environmentService.options!.profileToPreview!)));
|
||||
}
|
||||
|
||||
this.registerDropHandler();
|
||||
}
|
||||
|
||||
async handleURL(uri: URI): Promise<boolean> {
|
||||
|
||||
@@ -69,6 +69,7 @@ import { normalizeDriveLetter } from '../../../../base/common/labels.js';
|
||||
import { ActionBar } from '../../../../base/browser/ui/actionbar/actionbar.js';
|
||||
import { registerIcon } from '../../../../platform/theme/common/iconRegistry.js';
|
||||
import { DropdownMenuActionViewItem } from '../../../../base/browser/ui/dropdown/dropdownActionViewItem.js';
|
||||
import { IEnvironmentService } from '../../../../platform/environment/common/environment.js';
|
||||
|
||||
const editIcon = registerIcon('profiles-editor-edit-folder', Codicon.edit, localize('editIcon', 'Icon for the edit folder icon in the profiles editor.'));
|
||||
const removeIcon = registerIcon('profiles-editor-remove-folder', Codicon.close, localize('removeIcon', 'Icon for the remove folder icon in the profiles editor.'));
|
||||
@@ -2119,14 +2120,17 @@ class ChangeProfileAction implements IAction {
|
||||
readonly id = 'changeProfile';
|
||||
readonly label = 'Change Profile';
|
||||
readonly class = ThemeIcon.asClassName(editIcon);
|
||||
readonly enabled = true;
|
||||
readonly enabled: boolean;
|
||||
readonly tooltip = localize('change profile', "Change Profile");
|
||||
readonly checked = false;
|
||||
|
||||
constructor(
|
||||
private readonly item: WorkspaceTableElement,
|
||||
@IUserDataProfilesService private readonly userDataProfilesService: IUserDataProfilesService,
|
||||
@IUriIdentityService uriIdentityService: IUriIdentityService,
|
||||
@IEnvironmentService environmentService: IEnvironmentService,
|
||||
) {
|
||||
this.enabled = !uriIdentityService.extUri.isEqual(item.workspace, environmentService.agentSessionsWorkspace);
|
||||
}
|
||||
|
||||
run(): void { }
|
||||
@@ -2163,6 +2167,7 @@ class WorkspaceUriActionsColumnRenderer implements ITableRenderer<WorkspaceTable
|
||||
@IUserDataProfileManagementService private readonly userDataProfileManagementService: IUserDataProfileManagementService,
|
||||
@IContextMenuService private readonly contextMenuService: IContextMenuService,
|
||||
@IUriIdentityService private readonly uriIdentityService: IUriIdentityService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -2189,7 +2194,7 @@ class WorkspaceUriActionsColumnRenderer implements ITableRenderer<WorkspaceTable
|
||||
templateData.actionBar.clear();
|
||||
const actions: IAction[] = [];
|
||||
actions.push(this.createOpenAction(item));
|
||||
actions.push(new ChangeProfileAction(item, this.userDataProfilesService));
|
||||
actions.push(new ChangeProfileAction(item, this.userDataProfilesService, this.uriIdentityService, this.environmentService));
|
||||
actions.push(this.createDeleteAction(item));
|
||||
templateData.actionBar.push(actions, { icon: true });
|
||||
}
|
||||
@@ -2206,10 +2211,11 @@ class WorkspaceUriActionsColumnRenderer implements ITableRenderer<WorkspaceTable
|
||||
}
|
||||
|
||||
private createDeleteAction(item: WorkspaceTableElement): IAction {
|
||||
const isAgentSessionsWorkspace = this.uriIdentityService.extUri.isEqual(item.workspace, this.environmentService.agentSessionsWorkspace);
|
||||
return {
|
||||
label: '',
|
||||
class: ThemeIcon.asClassName(removeIcon),
|
||||
enabled: this.userDataProfileManagementService.getDefaultProfileToUse().id !== item.profileElement.profile.id,
|
||||
enabled: this.userDataProfileManagementService.getDefaultProfileToUse().id !== item.profileElement.profile.id && !isAgentSessionsWorkspace,
|
||||
id: 'deleteTrustedUri',
|
||||
tooltip: localize('deleteTrustedUri', "Delete Path"),
|
||||
run: () => item.profileElement.updateWorkspaces([], [item.workspace])
|
||||
|
||||
@@ -14,7 +14,7 @@ import { WorkspaceConfigurationModelParser, StandaloneConfigurationModelParser }
|
||||
import { TASKS_CONFIGURATION_KEY, FOLDER_SETTINGS_NAME, LAUNCH_CONFIGURATION_KEY, IConfigurationCache, ConfigurationKey, REMOTE_MACHINE_SCOPES, FOLDER_SCOPES, WORKSPACE_SCOPES, APPLY_ALL_PROFILES_SETTING, APPLICATION_SCOPES, MCP_CONFIGURATION_KEY } from '../common/configuration.js';
|
||||
import { IStoredWorkspaceFolder } from '../../../../platform/workspaces/common/workspaces.js';
|
||||
import { WorkbenchState, IWorkspaceFolder, IWorkspaceIdentifier } from '../../../../platform/workspace/common/workspace.js';
|
||||
import { ConfigurationScope, Extensions, IConfigurationRegistry, OVERRIDE_PROPERTY_REGEX } from '../../../../platform/configuration/common/configurationRegistry.js';
|
||||
import { ConfigurationScope, Extensions, IConfigurationDefaults, IConfigurationRegistry, OVERRIDE_PROPERTY_REGEX } from '../../../../platform/configuration/common/configurationRegistry.js';
|
||||
import { equals } from '../../../../base/common/objects.js';
|
||||
import { IRemoteAgentService } from '../../remote/common/remoteAgentService.js';
|
||||
import { hash } from '../../../../base/common/hash.js';
|
||||
@@ -23,11 +23,11 @@ import { ILogService } from '../../../../platform/log/common/log.js';
|
||||
import { IStringDictionary } from '../../../../base/common/collections.js';
|
||||
import { joinPath } from '../../../../base/common/resources.js';
|
||||
import { Registry } from '../../../../platform/registry/common/platform.js';
|
||||
import { IBrowserWorkbenchEnvironmentService } from '../../environment/browser/environmentService.js';
|
||||
import { isEmptyObject, isObject } from '../../../../base/common/types.js';
|
||||
import { DefaultConfiguration as BaseDefaultConfiguration } from '../../../../platform/configuration/common/configurations.js';
|
||||
import { IJSONEditingService } from '../common/jsonEditing.js';
|
||||
import { IUserDataProfilesService } from '../../../../platform/userDataProfile/common/userDataProfile.js';
|
||||
import { IBrowserWorkbenchEnvironmentService } from '../../environment/browser/environmentService.js';
|
||||
|
||||
export class DefaultConfiguration extends BaseDefaultConfiguration {
|
||||
|
||||
@@ -36,6 +36,7 @@ export class DefaultConfiguration extends BaseDefaultConfiguration {
|
||||
private readonly configurationRegistry = Registry.as<IConfigurationRegistry>(Extensions.Configuration);
|
||||
private cachedConfigurationDefaultsOverrides: IStringDictionary<unknown> = {};
|
||||
private readonly cacheKey: ConfigurationKey = { type: 'defaults', key: 'configurationDefaultsOverrides' };
|
||||
private profileDefaults: IConfigurationDefaults | undefined;
|
||||
|
||||
constructor(
|
||||
private readonly configurationCache: IConfigurationCache,
|
||||
@@ -67,6 +68,18 @@ export class DefaultConfiguration extends BaseDefaultConfiguration {
|
||||
return !isEmptyObject(this.cachedConfigurationDefaultsOverrides);
|
||||
}
|
||||
|
||||
updateProfileDefaults(configurationDefaults: IStringDictionary<unknown> | undefined): void {
|
||||
if (this.profileDefaults) {
|
||||
this.configurationRegistry.deregisterDefaultConfigurations([this.profileDefaults]);
|
||||
}
|
||||
if (configurationDefaults) {
|
||||
this.profileDefaults = { overrides: configurationDefaults };
|
||||
this.configurationRegistry.registerDefaultConfigurations([this.profileDefaults]);
|
||||
} else {
|
||||
this.profileDefaults = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
private initiaizeCachedConfigurationDefaultsOverridesPromise: Promise<void> | undefined;
|
||||
private initializeCachedConfigurationDefaultsOverrides(): Promise<void> {
|
||||
if (!this.initiaizeCachedConfigurationDefaultsOverridesPromise) {
|
||||
|
||||
@@ -125,6 +125,9 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat
|
||||
this.initRemoteUserConfigurationBarrier = new Barrier();
|
||||
this.completeWorkspaceBarrier = new Barrier();
|
||||
this.defaultConfiguration = this._register(new DefaultConfiguration(configurationCache, environmentService, logService));
|
||||
if (this.userDataProfileService.currentProfile.templateData?.settings) {
|
||||
this.defaultConfiguration.updateProfileDefaults(this.userDataProfileService.currentProfile.templateData?.settings);
|
||||
}
|
||||
this.policyConfiguration = policyService instanceof NullPolicyService ? new NullPolicyConfiguration() : this._register(new PolicyConfiguration(this.defaultConfiguration, policyService, logService));
|
||||
this.configurationCache = configurationCache;
|
||||
this._configuration = new Configuration(this.defaultConfiguration.configurationModel, this.policyConfiguration.configurationModel, ConfigurationModel.createEmptyModel(logService), ConfigurationModel.createEmptyModel(logService), ConfigurationModel.createEmptyModel(logService), ConfigurationModel.createEmptyModel(logService), new ResourceMap(), ConfigurationModel.createEmptyModel(logService), new ResourceMap<ConfigurationModel>(), this.workspace, logService);
|
||||
@@ -729,6 +732,9 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat
|
||||
promises.push(this.reloadApplicationConfiguration(true));
|
||||
}
|
||||
}
|
||||
if (!equals(e.previous.templateData?.settings, e.profile.templateData?.settings)) {
|
||||
this.defaultConfiguration.updateProfileDefaults(e.profile.templateData?.settings);
|
||||
}
|
||||
let [localUser, application] = await Promise.all(promises);
|
||||
application = application ?? this._configuration.applicationConfiguration;
|
||||
if (this.applicationConfiguration) {
|
||||
|
||||
@@ -138,6 +138,9 @@ export class BrowserWorkbenchEnvironmentService implements IBrowserWorkbenchEnvi
|
||||
@memoize
|
||||
get untitledWorkspacesHome(): URI { return joinPath(this.userRoamingDataHome, 'Workspaces'); }
|
||||
|
||||
@memoize
|
||||
get builtinProfilesHome(): URI { return joinPath(this.userRoamingDataHome, 'builtinProfiles'); }
|
||||
|
||||
@memoize
|
||||
get serviceMachineIdResource(): URI { return joinPath(this.userRoamingDataHome, 'machineid'); }
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ export interface IWorkbenchEnvironmentService extends IEnvironmentService {
|
||||
readonly skipWelcome: boolean;
|
||||
readonly disableWorkspaceTrust: boolean;
|
||||
readonly webviewExternalEndpoint: string;
|
||||
readonly agentSessionsWindow?: boolean;
|
||||
|
||||
// --- Development
|
||||
readonly debugRenderer: boolean;
|
||||
|
||||
@@ -13,8 +13,9 @@ import { memoize } from '../../../../base/common/decorators.js';
|
||||
import { URI } from '../../../../base/common/uri.js';
|
||||
import { Schemas } from '../../../../base/common/network.js';
|
||||
import { IProductService } from '../../../../platform/product/common/productService.js';
|
||||
import { joinPath } from '../../../../base/common/resources.js';
|
||||
import { isEqual, joinPath } from '../../../../base/common/resources.js';
|
||||
import { VSBuffer } from '../../../../base/common/buffer.js';
|
||||
import { isWorkspaceIdentifier } from '../../../../platform/workspace/common/workspace.js';
|
||||
|
||||
export const INativeWorkbenchEnvironmentService = refineServiceDecorator<IEnvironmentService, INativeWorkbenchEnvironmentService>(IEnvironmentService);
|
||||
|
||||
@@ -147,6 +148,11 @@ export class NativeWorkbenchEnvironmentService extends AbstractNativeEnvironment
|
||||
@memoize
|
||||
get filesToWait(): IPathsToWaitFor | undefined { return this.configuration.filesToWait; }
|
||||
|
||||
@memoize
|
||||
get agentSessionsWindow(): boolean | undefined {
|
||||
return isWorkspaceIdentifier(this.configuration.workspace) && isEqual(this.configuration.workspace.configPath, this.agentSessionsWorkspace);
|
||||
}
|
||||
|
||||
constructor(
|
||||
private readonly configuration: INativeWindowConfiguration,
|
||||
productService: IProductService
|
||||
|
||||
Reference in New Issue
Block a user