Path: blob/main/src/vs/workbench/contrib/chat/common/chatWidgetHistoryService.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { Emitter, Event } from '../../../../base/common/event.js';6import { URI } from '../../../../base/common/uri.js';7import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';8import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js';9import { Memento } from '../../../common/memento.js';10import { ModifiedFileEntryState } from './chatEditingService.js';11import { CHAT_PROVIDER_ID } from './chatParticipantContribTypes.js';12import { IChatRequestVariableEntry } from './chatVariableEntries.js';13import { ChatAgentLocation, ChatModeKind } from './constants.js';1415export interface IChatHistoryEntry {16text: string;17state?: IChatInputState;18}1920/** The collected input state of ChatWidget contribs + attachments */21export interface IChatInputState {22[key: string]: any;23chatContextAttachments?: ReadonlyArray<IChatRequestVariableEntry>;24chatWorkingSet?: ReadonlyArray<{ uri: URI; state: ModifiedFileEntryState }>;2526/**27* This should be a mode id (ChatMode | string).28* { id: string } is the old IChatMode. This is deprecated but may still be in persisted data.29*/30chatMode?: ChatModeKind | string | { id: string };31}3233export const IChatWidgetHistoryService = createDecorator<IChatWidgetHistoryService>('IChatWidgetHistoryService');34export interface IChatWidgetHistoryService {35_serviceBrand: undefined;3637readonly onDidClearHistory: Event<void>;3839clearHistory(): void;40getHistory(location: ChatAgentLocation): IChatHistoryEntry[];41saveHistory(location: ChatAgentLocation, history: IChatHistoryEntry[]): void;42}4344interface IChatHistory {45history: { [providerId: string]: IChatHistoryEntry[] };46}4748export const ChatInputHistoryMaxEntries = 40;4950export class ChatWidgetHistoryService implements IChatWidgetHistoryService {51_serviceBrand: undefined;5253private memento: Memento;54private viewState: IChatHistory;5556private readonly _onDidClearHistory = new Emitter<void>();57readonly onDidClearHistory: Event<void> = this._onDidClearHistory.event;5859constructor(60@IStorageService storageService: IStorageService61) {62this.memento = new Memento('interactive-session', storageService);63const loadedState = this.memento.getMemento(StorageScope.WORKSPACE, StorageTarget.MACHINE) as IChatHistory;64for (const provider in loadedState.history) {65// Migration from old format66loadedState.history[provider] = loadedState.history[provider].map(entry => typeof entry === 'string' ? { text: entry } : entry);67}6869this.viewState = loadedState;70}7172getHistory(location: ChatAgentLocation): IChatHistoryEntry[] {73const key = this.getKey(location);74return this.viewState.history?.[key] ?? [];75}7677private getKey(location: ChatAgentLocation): string {78// Preserve history for panel by continuing to use the same old provider id. Use the location as a key for other chat locations.79return location === ChatAgentLocation.Panel ? CHAT_PROVIDER_ID : location;80}8182saveHistory(location: ChatAgentLocation, history: IChatHistoryEntry[]): void {83if (!this.viewState.history) {84this.viewState.history = {};85}8687const key = this.getKey(location);88this.viewState.history[key] = history.slice(-ChatInputHistoryMaxEntries);89this.memento.saveMemento();90}9192clearHistory(): void {93this.viewState.history = {};94this.memento.saveMemento();95this._onDidClearHistory.fire();96}97}9899100