diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatTransfer.ts b/src/vs/workbench/contrib/chat/browser/actions/chatTransfer.ts index 52bc3680170..8825330db97 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatTransfer.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatTransfer.ts @@ -14,6 +14,6 @@ export class ChatTransferContribution extends Disposable implements IWorkbenchCo @IChatTransferService chatTransferService: IChatTransferService, ) { super(); - chatTransferService.checkAndSetWorkspaceTrust(); + chatTransferService.checkAndSetTransferredWorkspaceTrust(); } } diff --git a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts index 5c61e6ab2e9..99332683322 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts @@ -631,6 +631,7 @@ registerChatToolActions(); registerEditorFeature(ChatPasteProvidersFeature); +registerSingleton(IChatTransferService, ChatTransferService, InstantiationType.Delayed); registerSingleton(IChatService, ChatService, InstantiationType.Delayed); registerSingleton(IChatWidgetService, ChatWidgetService, InstantiationType.Delayed); registerSingleton(IQuickChatService, QuickChatService, InstantiationType.Delayed); @@ -651,6 +652,5 @@ registerSingleton(IChatMarkdownAnchorService, ChatMarkdownAnchorService, Instant registerSingleton(ILanguageModelIgnoredFilesService, LanguageModelIgnoredFilesService, InstantiationType.Delayed); registerSingleton(IChatEntitlementService, ChatEntitlementService, InstantiationType.Delayed); registerSingleton(IPromptsService, PromptsService, InstantiationType.Delayed); -registerSingleton(IChatTransferService, ChatTransferService, InstantiationType.Delayed); registerWorkbenchContribution2(ChatEditingNotebookFileSystemProviderContrib.ID, ChatEditingNotebookFileSystemProviderContrib, WorkbenchPhase.BlockStartup); diff --git a/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts b/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts index 5a734d53c25..4c34ebe849c 100644 --- a/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts +++ b/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts @@ -34,6 +34,7 @@ import { IChatCompleteResponse, IChatDetail, IChatFollowup, IChatProgress, IChat import { ChatServiceTelemetry } from './chatServiceTelemetry.js'; import { ChatSessionStore, IChatTransfer2 } from './chatSessionStore.js'; import { IChatSlashCommandService } from './chatSlashCommands.js'; +import { IChatTransferService } from './chatTransferService.js'; import { IChatVariablesService } from './chatVariables.js'; import { ChatAgentLocation, ChatConfiguration, ChatMode } from './constants.js'; import { ChatMessageRole, IChatMessage } from './languageModels.js'; @@ -158,6 +159,7 @@ export class ChatService extends Disposable implements IChatService { @IChatAgentService private readonly chatAgentService: IChatAgentService, @IConfigurationService private readonly configurationService: IConfigurationService, @IWorkbenchAssignmentService private readonly experimentService: IWorkbenchAssignmentService, + @IChatTransferService private readonly chatTransferService: IChatTransferService, ) { super(); @@ -1128,6 +1130,7 @@ export class ChatService extends Disposable implements IChatService { }); this.storageService.store(globalChatKey, JSON.stringify(existingRaw), StorageScope.PROFILE, StorageTarget.MACHINE); + this.chatTransferService.addWorkspaceToTransferred(toWorkspace); this.trace('transferChatSession', `Transferred session ${model.sessionId} to workspace ${toWorkspace.toString()}`); } diff --git a/src/vs/workbench/contrib/chat/common/chatTransferService.ts b/src/vs/workbench/contrib/chat/common/chatTransferService.ts index 22a2eb31aa8..bbc21070343 100644 --- a/src/vs/workbench/contrib/chat/common/chatTransferService.ts +++ b/src/vs/workbench/contrib/chat/common/chatTransferService.ts @@ -3,18 +3,21 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { IWorkspaceContextService } from '../../../../platform/workspace/common/workspace.js'; -import { IStorageService } from '../../../../platform/storage/common/storage.js'; +import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js'; import { IFileService } from '../../../../platform/files/common/files.js'; import { IWorkspaceTrustManagementService } from '../../../../platform/workspace/common/workspaceTrust.js'; -import { isChatTransferredWorkspace, areWorkspaceFoldersEmpty } from '../../../services/workspaces/common/workspaceUtils.js'; +import { areWorkspaceFoldersEmpty } from '../../../services/workspaces/common/workspaceUtils.js'; import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js'; +import { URI } from '../../../../base/common/uri.js'; export const IChatTransferService = createDecorator('chatTransferService'); +const transferredWorkspacesKey = 'chat.transferedWorkspaces'; export interface IChatTransferService { readonly _serviceBrand: undefined; - checkAndSetWorkspaceTrust(): Promise; + checkAndSetTransferredWorkspaceTrust(): Promise; + addWorkspaceToTransferred(workspace: URI): void; } export class ChatTransferService implements IChatTransferService { @@ -27,10 +30,35 @@ export class ChatTransferService implements IChatTransferService { @IWorkspaceTrustManagementService private readonly workspaceTrustManagementService: IWorkspaceTrustManagementService ) { } - async checkAndSetWorkspaceTrust(): Promise { + deleteWorkspaceFromTransferredList(workspace: URI): void { + const transferredWorkspaces = this.storageService.getObject(transferredWorkspacesKey, StorageScope.PROFILE, []); + const updatedWorkspaces = transferredWorkspaces.filter(uri => uri !== workspace.toString()); + this.storageService.store(transferredWorkspacesKey, updatedWorkspaces, StorageScope.PROFILE, StorageTarget.MACHINE); + } + + addWorkspaceToTransferred(workspace: URI): void { + const transferredWorkspaces = this.storageService.getObject(transferredWorkspacesKey, StorageScope.PROFILE, []); + transferredWorkspaces.push(workspace.toString()); + this.storageService.store(transferredWorkspacesKey, transferredWorkspaces, StorageScope.PROFILE, StorageTarget.MACHINE); + } + + async checkAndSetTransferredWorkspaceTrust(): Promise { const workspace = this.workspaceService.getWorkspace(); - if (isChatTransferredWorkspace(workspace, this.storageService) && await areWorkspaceFoldersEmpty(workspace, this.fileService)) { + const currentWorkspaceUri = workspace.folders[0]?.uri; + if (!currentWorkspaceUri) { + return; + } + if (this.isChatTransferredWorkspace(currentWorkspaceUri, this.storageService) && await areWorkspaceFoldersEmpty(workspace, this.fileService)) { await this.workspaceTrustManagementService.setWorkspaceTrust(true); + this.deleteWorkspaceFromTransferredList(currentWorkspaceUri); } } + + isChatTransferredWorkspace(workspace: URI, storageService: IStorageService): boolean { + if (!workspace) { + return false; + } + const chatWorkspaceTransfer: URI[] = storageService.getObject(transferredWorkspacesKey, StorageScope.PROFILE, []); + return chatWorkspaceTransfer.some(item => item.toString() === workspace.toString()); + } } diff --git a/src/vs/workbench/contrib/chat/test/browser/chatEditingService.test.ts b/src/vs/workbench/contrib/chat/test/browser/chatEditingService.test.ts index f7612029ae7..6056df9b990 100644 --- a/src/vs/workbench/contrib/chat/test/browser/chatEditingService.test.ts +++ b/src/vs/workbench/contrib/chat/test/browser/chatEditingService.test.ts @@ -33,6 +33,7 @@ import { INotebookService } from '../../../notebook/common/notebookService.js'; import { Range } from '../../../../../editor/common/core/range.js'; import { ChatAgentLocation } from '../../common/constants.js'; import { NotebookTextModel } from '../../../notebook/common/model/notebookTextModel.js'; +import { ChatTransferService, IChatTransferService } from '../../common/chatTransferService.js'; function getAgentData(id: string) { return { @@ -62,6 +63,7 @@ suite('ChatEditingService', function () { collection.set(IChatAgentService, new SyncDescriptor(ChatAgentService)); collection.set(IChatVariablesService, new MockChatVariablesService()); collection.set(IChatSlashCommandService, new class extends mock() { }); + collection.set(IChatTransferService, new SyncDescriptor(ChatTransferService)); collection.set(IChatEditingService, new SyncDescriptor(ChatEditingService)); collection.set(IChatService, new SyncDescriptor(ChatService)); collection.set(IMultiDiffSourceResolverService, new class extends mock() { diff --git a/src/vs/workbench/contrib/inlineChat/test/browser/inlineChatSession.test.ts b/src/vs/workbench/contrib/inlineChat/test/browser/inlineChatSession.test.ts index 5e2024222e7..1efc0b9e286 100644 --- a/src/vs/workbench/contrib/inlineChat/test/browser/inlineChatSession.test.ts +++ b/src/vs/workbench/contrib/inlineChat/test/browser/inlineChatSession.test.ts @@ -63,6 +63,7 @@ import { assertSnapshot } from '../../../../../base/test/common/snapshot.js'; import { IObservable, constObservable } from '../../../../../base/common/observable.js'; import { IChatEditingService, IChatEditingSession } from '../../../chat/common/chatEditingService.js'; import { ChatAgentLocation } from '../../../chat/common/constants.js'; +import { ChatTransferService, IChatTransferService } from '../../../chat/common/chatTransferService.js'; suite('InlineChatSession', function () { @@ -89,6 +90,7 @@ suite('InlineChatSession', function () { [IChatWidgetHistoryService, new SyncDescriptor(ChatWidgetHistoryService)], [IChatWidgetService, new SyncDescriptor(ChatWidgetService)], [IChatSlashCommandService, new SyncDescriptor(ChatSlashCommandService)], + [IChatTransferService, new SyncDescriptor(ChatTransferService)], [IChatService, new SyncDescriptor(ChatService)], [IEditorWorkerService, new SyncDescriptor(TestWorkerService)], [IChatAgentService, new SyncDescriptor(ChatAgentService)], diff --git a/src/vs/workbench/services/workspaces/common/workspaceUtils.ts b/src/vs/workbench/services/workspaces/common/workspaceUtils.ts index 4ba2f5af24a..a67b3457ad0 100644 --- a/src/vs/workbench/services/workspaces/common/workspaceUtils.ts +++ b/src/vs/workbench/services/workspaces/common/workspaceUtils.ts @@ -2,22 +2,8 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { URI } from '../../../../base/common/uri.js'; import { IWorkspace } from '../../../../platform/workspace/common/workspace.js'; import { IFileService } from '../../../../platform/files/common/files.js'; -import { IStorageService, StorageScope } from '../../../../platform/storage/common/storage.js'; - -export function isChatTransferredWorkspace(workspace: IWorkspace, storageService: IStorageService): boolean { - const workspaceUri = workspace.folders[0]?.uri; - if (!workspaceUri) { - return false; - } - const chatWorkspaceTransfer = storageService.getObject('chat.workspaceTransfer', StorageScope.PROFILE, []); - const toWorkspace: { toWorkspace: URI }[] = chatWorkspaceTransfer.map((item: any) => { - return { toWorkspace: URI.from(item.toWorkspace) }; - }); - return toWorkspace.some(item => item.toWorkspace.toString() === workspaceUri.toString()); -} export async function areWorkspaceFoldersEmpty(workspace: IWorkspace, fileService: IFileService): Promise { for (const folder of workspace.folders) {