Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 18 additions & 1 deletion src/extension/tools/common/agentMemoryService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,22 @@ export interface IAgentMemoryService {

export const IAgentMemoryService = createServiceIdentifier<IAgentMemoryService>('IAgentMemoryService');

/**
* Returns true if the chat.copilotMemory.enabled config is enabled and editor preview features
* are allowed by organization policy. Defaults to false when the Copilot token is unavailable
* (conservative behavior when authentication hasn't completed yet).
*/
export function isCopilotMemoryConfigEnabled(
authenticationService: IAuthenticationService,
configurationService: IConfigurationService,
experimentationService: IExperimentationService
): boolean {
if (!authenticationService.copilotToken?.isEditorPreviewFeaturesEnabled()) {
return false;
}
return configurationService.getExperimentBasedConfig(ConfigKey.CopilotMemoryEnabled, experimentationService);
}

export class AgentMemoryService extends Disposable implements IAgentMemoryService {
declare readonly _serviceBrand: undefined;

Expand Down Expand Up @@ -153,9 +169,10 @@ export class AgentMemoryService extends Disposable implements IAgentMemoryServic
/**
* Check if the chat.copilotMemory.enabled config is enabled.
* Uses experiment-based configuration for gradual rollout.
* Returns false if editor preview features are disabled by organization policy.
*/
private isCAPIMemorySyncConfigEnabled(): boolean {
return this.configService.getExperimentBasedConfig(ConfigKey.CopilotMemoryEnabled, this.experimentationService);
return isCopilotMemoryConfigEnabled(this.authenticationService, this.configService, this.experimentationService);
}

async checkMemoryEnabled(): Promise<boolean> {
Expand Down
9 changes: 6 additions & 3 deletions src/extension/tools/node/memoryContextPrompt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import { BasePromptElementProps, PromptElement, PromptElementProps, PromptSizing } from '@vscode/prompt-tsx';
import { IAuthenticationService } from '../../../platform/authentication/common/authentication';
import { ConfigKey, IConfigurationService } from '../../../platform/configuration/common/configurationService';
import { IVSCodeExtensionContext } from '../../../platform/extContext/common/extensionContext';
import { IFileSystemService } from '../../../platform/filesystem/common/fileSystemService';
Expand All @@ -12,7 +13,7 @@ import { IExperimentationService } from '../../../platform/telemetry/common/null
import { ITelemetryService } from '../../../platform/telemetry/common/telemetry';
import { URI } from '../../../util/vs/base/common/uri';
import { Tag } from '../../prompts/node/base/tag';
import { IAgentMemoryService, normalizeCitations, RepoMemoryEntry } from '../common/agentMemoryService';
import { IAgentMemoryService, isCopilotMemoryConfigEnabled, normalizeCitations, RepoMemoryEntry } from '../common/agentMemoryService';
import { ToolName } from '../common/toolNames';
import { extractSessionId } from './memoryTool';

Expand All @@ -27,6 +28,7 @@ export class MemoryContextPrompt extends PromptElement<MemoryContextPromptProps>
constructor(
props: any,
@IAgentMemoryService private readonly agentMemoryService: IAgentMemoryService,
@IAuthenticationService private readonly authenticationService: IAuthenticationService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IExperimentationService private readonly experimentationService: IExperimentationService,
@IVSCodeExtensionContext private readonly extensionContext: IVSCodeExtensionContext,
Expand All @@ -37,7 +39,7 @@ export class MemoryContextPrompt extends PromptElement<MemoryContextPromptProps>
}

async render() {
const enableCopilotMemory = this.configurationService.getExperimentBasedConfig(ConfigKey.CopilotMemoryEnabled, this.experimentationService);
const enableCopilotMemory = isCopilotMemoryConfigEnabled(this.authenticationService, this.configurationService, this.experimentationService);
const enableMemoryTool = this.configurationService.getExperimentBasedConfig(ConfigKey.MemoryToolEnabled, this.experimentationService);

const userMemoryContent = enableMemoryTool ? await this.getUserMemoryContent() : undefined;
Expand Down Expand Up @@ -250,14 +252,15 @@ export class MemoryContextPrompt extends PromptElement<MemoryContextPromptProps>
export class MemoryInstructionsPrompt extends PromptElement<BasePromptElementProps> {
constructor(
props: PromptElementProps<BasePromptElementProps>,
@IAuthenticationService private readonly authenticationService: IAuthenticationService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IExperimentationService private readonly experimentationService: IExperimentationService,
) {
super(props);
}

async render(state: void, sizing: PromptSizing) {
const enableCopilotMemory = this.configurationService.getExperimentBasedConfig(ConfigKey.CopilotMemoryEnabled, this.experimentationService);
const enableCopilotMemory = isCopilotMemoryConfigEnabled(this.authenticationService, this.configurationService, this.experimentationService);
const enableMemoryTool = this.configurationService.getExperimentBasedConfig(ConfigKey.MemoryToolEnabled, this.experimentationService);
if (!enableCopilotMemory && !enableMemoryTool) {
return null;
Expand Down
6 changes: 4 additions & 2 deletions src/extension/tools/node/memoryTool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import * as l10n from '@vscode/l10n';
import type * as vscode from 'vscode';
import { IAuthenticationService } from '../../../platform/authentication/common/authentication';
import { ConfigKey, IConfigurationService } from '../../../platform/configuration/common/configurationService';
import { IVSCodeExtensionContext } from '../../../platform/extContext/common/extensionContext';
import { createDirectoryIfNotExists, IFileSystemService } from '../../../platform/filesystem/common/fileSystemService';
Expand All @@ -15,7 +16,7 @@ import { ITelemetryService } from '../../../platform/telemetry/common/telemetry'
import { CancellationToken } from '../../../util/vs/base/common/cancellation';
import { URI } from '../../../util/vs/base/common/uri';
import { LanguageModelTextPart, LanguageModelToolResult, MarkdownString } from '../../../vscodeTypes';
import { IAgentMemoryService, RepoMemoryEntry } from '../common/agentMemoryService';
import { IAgentMemoryService, isCopilotMemoryConfigEnabled, RepoMemoryEntry } from '../common/agentMemoryService';
import { IMemoryCleanupService } from '../common/memoryCleanupService';
import { ToolName } from '../common/toolNames';
import { ICopilotTool, ToolRegistry } from '../common/toolsRegistry';
Expand Down Expand Up @@ -157,6 +158,7 @@ export class MemoryTool implements ICopilotTool<MemoryToolParams> {
@IMemoryCleanupService private readonly memoryCleanupService: IMemoryCleanupService,
@IVSCodeExtensionContext private readonly extensionContext: IVSCodeExtensionContext,
@ILogService private readonly logService: ILogService,
@IAuthenticationService private readonly authenticationService: IAuthenticationService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IExperimentationService private readonly experimentationService: IExperimentationService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
Expand Down Expand Up @@ -542,7 +544,7 @@ export class MemoryTool implements ICopilotTool<MemoryToolParams> {
}

// List local repo memory files under repo/ (only when CAPI is not enabled)
const capiEnabled = this.configurationService.getExperimentBasedConfig(ConfigKey.CopilotMemoryEnabled, this.experimentationService);
const capiEnabled = isCopilotMemoryConfigEnabled(this.authenticationService, this.configurationService, this.experimentationService);
if (!capiEnabled) {
try {
const repoUri = this._resolveUri('/memories/repo/', 'repo');
Expand Down
7 changes: 5 additions & 2 deletions src/extension/tools/vscode-node/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@

import * as vscode from 'vscode';
import { l10n } from 'vscode';
import { ConfigKey, IConfigurationService } from '../../../platform/configuration/common/configurationService';
import { IAuthenticationService } from '../../../platform/authentication/common/authentication';
import { IConfigurationService } from '../../../platform/configuration/common/configurationService';
import { IVSCodeExtensionContext } from '../../../platform/extContext/common/extensionContext';
import { IFileSystemService } from '../../../platform/filesystem/common/fileSystemService';
import { FileType } from '../../../platform/filesystem/common/fileTypes';
import { IExperimentationService } from '../../../platform/telemetry/common/nullExperimentationService';
import { Disposable, DisposableMap } from '../../../util/vs/base/common/lifecycle';
import { autorun, autorunIterableDelta } from '../../../util/vs/base/common/observableInternal';
import { URI } from '../../../util/vs/base/common/uri';
import { isCopilotMemoryConfigEnabled } from '../common/agentMemoryService';
import { getContributedToolName } from '../common/toolNames';
import { isVscodeLanguageModelTool } from '../common/toolsRegistry';
import { IToolsService } from '../common/toolsService';
Expand All @@ -27,6 +29,7 @@ export class ToolsContribution extends Disposable {
@IToolGroupingCache toolGrouping: IToolGroupingCache,
@IToolGroupingService toolGroupingService: IToolGroupingService,
@IVSCodeExtensionContext private readonly extensionContext: IVSCodeExtensionContext,
@IAuthenticationService private readonly authenticationService: IAuthenticationService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IExperimentationService private readonly experimentationService: IExperimentationService,
@IFileSystemService private readonly fileSystemService: IFileSystemService,
Expand Down Expand Up @@ -92,7 +95,7 @@ export class ToolsContribution extends Disposable {
}

// Collect local repo-scoped memories only when CAPI memory is disabled
const capiMemoryEnabled = this.configurationService.getExperimentBasedConfig(ConfigKey.CopilotMemoryEnabled, this.experimentationService);
const capiMemoryEnabled = isCopilotMemoryConfigEnabled(this.authenticationService, this.configurationService, this.experimentationService);
if (storageUri && !capiMemoryEnabled) {
const repoMemoryUri = URI.joinPath(storageUri, 'memory-tool/memories/repo');
try {
Expand Down
2 changes: 1 addition & 1 deletion test/base/extHostContext/simulationExtHostToolsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export class SimulationExtHostToolsService extends BaseToolsService implements I
}

private ensureToolsRegistered() {
this._lmToolRegistration ??= new ToolsContribution(this, {} as any, { threshold: observableValue(this, 128) } as any, {} as any, {} as any, {} as any, {} as any);
this._lmToolRegistration ??= new ToolsContribution(this, {} as any, { threshold: observableValue(this, 128) } as any, {} as any, {} as any, {} as any, {} as any, {} as any);
}

getCopilotTool(name: string): ICopilotTool<any> | undefined {
Expand Down
Loading