diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatImportExport.ts b/src/vs/workbench/contrib/chat/browser/actions/chatImportExport.ts index 1baa73540e5..28eafd2107f 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatImportExport.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatImportExport.ts @@ -11,7 +11,7 @@ import { Action2, registerAction2 } from '../../../../../platform/actions/common import { IFileDialogService } from '../../../../../platform/dialogs/common/dialogs.js'; import { IFileService } from '../../../../../platform/files/common/files.js'; import { CHAT_CATEGORY } from './chatActions.js'; -import { IChatWidgetService } from '../chat.js'; +import { ChatViewPaneTarget, IChatWidgetService } from '../chat.js'; import { IChatEditorOptions } from '../widgetHosts/editor/chatEditor.js'; import { ChatEditorInput } from '../widgetHosts/editor/chatEditorInput.js'; import { ChatContextKeys } from '../../common/actions/chatContextKeys.js'; @@ -23,6 +23,18 @@ import { revive } from '../../../../../base/common/marshalling.js'; const defaultFileName = 'chat.json'; const filters = [{ name: localize('chat.file.label', "Chat Session"), extensions: ['json'] }]; +/** + * Target location for importing a chat session. + * - 'chatViewPane': Opens in the chat view pane (sidebar/panel) + * - 'default': Opens in the active editor group + */ +export type ChatImportTarget = 'chatViewPane' | 'default'; + +export interface ChatImportOptions { + inputPath?: URI; + target?: ChatImportTarget; +} + export function registerChatExportActions() { registerAction2(class ExportChatAction extends Action2 { constructor() { @@ -78,30 +90,52 @@ export function registerChatExportActions() { f1: true, }); } - async run(accessor: ServicesAccessor, ...args: unknown[]) { - const fileDialogService = accessor.get(IFileDialogService); + async run(accessor: ServicesAccessor, opts?: ChatImportOptions) { const fileService = accessor.get(IFileService); const widgetService = accessor.get(IChatWidgetService); + const chatService = accessor.get(IChatService); + const fileDialogService = accessor.get(IFileDialogService); - const defaultUri = joinPath(await fileDialogService.defaultFilePath(), defaultFileName); - const result = await fileDialogService.showOpenDialog({ - defaultUri, - canSelectFiles: true, - filters - }); - if (!result) { - return; + let inputPath = opts?.inputPath; + if (!inputPath) { + const defaultUri = joinPath(await fileDialogService.defaultFilePath(), defaultFileName); + const result = await fileDialogService.showOpenDialog({ + defaultUri, + canSelectFiles: true, + filters + }); + if (!result) { + return; + } + inputPath = result[0]; } - const content = await fileService.readFile(result[0]); + const content = await fileService.readFile(inputPath); try { const data = revive(JSON.parse(content.value.toString())); if (!isExportableSessionData(data)) { throw new Error('Invalid chat session data'); } - const options: IChatEditorOptions = { target: { data }, pinned: true }; - await widgetService.openSession(ChatEditorInput.getNewEditorUri(), undefined, options); + let sessionResource: URI; + let resolvedTarget: typeof ChatViewPaneTarget | undefined; + let options: IChatEditorOptions; + + if (opts?.target === 'chatViewPane') { + const modelRef = chatService.loadSessionFromContent(data); + if (!modelRef) { + return; + } + sessionResource = modelRef.object.sessionResource; + resolvedTarget = ChatViewPaneTarget; + options = { pinned: true }; + } else { + sessionResource = ChatEditorInput.getNewEditorUri(); + resolvedTarget = undefined; + options = { target: { data }, pinned: true }; + } + + await widgetService.openSession(sessionResource, resolvedTarget, options); } catch (err) { throw err; }