chat: cleanup most flagrant usages of IChatWidgetService.lastFocusedWidget (#278861)

Closes https://github.com/microsoft/vscode/issues/278638 mostly
This commit is contained in:
Connor Peet
2025-11-21 20:52:26 +00:00
committed by GitHub
parent 40c75b98e0
commit 9243a001aa
15 changed files with 61 additions and 59 deletions
@@ -34,14 +34,14 @@ class AnnounceChatConfirmationAction extends Action2 {
async run(accessor: ServicesAccessor): Promise<void> {
const chatWidgetService = accessor.get(IChatWidgetService);
const lastFocusedWidget = chatWidgetService.lastFocusedWidget;
const pendingWidget = chatWidgetService.getAllWidgets().find(widget => widget.viewModel?.model.requestNeedsInput.get());
if (!lastFocusedWidget) {
if (!pendingWidget) {
alert(localize('noChatSession', 'No active chat session found.'));
return;
}
const viewModel = lastFocusedWidget.viewModel;
const viewModel = pendingWidget.viewModel;
if (!viewModel) {
alert(localize('chatNotReady', 'Chat interface not ready.'));
return;
@@ -53,7 +53,7 @@ class AnnounceChatConfirmationAction extends Action2 {
const lastResponse = viewModel.getItems()[viewModel.getItems().length - 1];
if (isResponseVM(lastResponse)) {
// eslint-disable-next-line no-restricted-syntax
const confirmationWidgets = lastFocusedWidget.domNode.querySelectorAll('.chat-confirmation-widget-container');
const confirmationWidgets = pendingWidget.domNode.querySelectorAll('.chat-confirmation-widget-container');
if (confirmationWidgets.length > 0) {
firstConfirmationElement = confirmationWidgets[0] as HTMLElement;
}
@@ -8,11 +8,11 @@ import { ServicesAccessor } from '../../../../../editor/browser/editorExtensions
import { localize2 } from '../../../../../nls.js';
import { Action2, MenuId, registerAction2 } from '../../../../../platform/actions/common/actions.js';
import { IClipboardService } from '../../../../../platform/clipboard/common/clipboardService.js';
import { CHAT_CATEGORY, stringifyItem } from './chatActions.js';
import { ChatTreeItem, IChatWidgetService } from '../chat.js';
import { katexContainerClassName, katexContainerLatexAttributeName } from '../../../markdown/common/markedKatexExtension.js';
import { ChatContextKeys } from '../../common/chatContextKeys.js';
import { IChatRequestViewModel, IChatResponseViewModel, isChatTreeItem, isRequestVM, isResponseVM } from '../../common/chatViewModel.js';
import { katexContainerClassName, katexContainerLatexAttributeName } from '../../../markdown/common/markedKatexExtension.js';
import { ChatTreeItem, IChatWidgetService } from '../chat.js';
import { CHAT_CATEGORY, stringifyItem } from './chatActions.js';
export function registerChatCopyActions() {
registerAction2(class CopyAllAction extends Action2 {
@@ -30,10 +30,10 @@ export function registerChatCopyActions() {
});
}
run(accessor: ServicesAccessor, ...args: unknown[]) {
run(accessor: ServicesAccessor, context?: ChatTreeItem) {
const clipboardService = accessor.get(IClipboardService);
const chatWidgetService = accessor.get(IChatWidgetService);
const widget = chatWidgetService.lastFocusedWidget;
const widget = (context?.sessionResource && chatWidgetService.getWidgetBySessionResource(context.sessionResource)) || chatWidgetService.lastFocusedWidget;
if (widget) {
const viewModel = widget.viewModel;
const sessionAsText = viewModel?.getItems()
@@ -16,6 +16,7 @@ import { KeybindingWeight } from '../../../../../platform/keybinding/common/keyb
import { ActiveEditorContext } from '../../../../common/contextkeys.js';
import { ChatContextKeys } from '../../common/chatContextKeys.js';
import { IChatEditingSession } from '../../common/chatEditingService.js';
import { IChatService } from '../../common/chatService.js';
import { ChatAgentLocation, ChatModeKind } from '../../common/constants.js';
import { ChatViewId, IChatWidgetService } from '../chat.js';
import { EditingSessionAction, getEditingSessionContext } from '../chatEditing/chatEditingActions.js';
@@ -204,9 +205,9 @@ export function registerNewChatActions() {
}
async runEditingSessionAction(accessor: ServicesAccessor, editingSession: IChatEditingSession) {
const widget = accessor.get(IChatWidgetService);
const chatService = accessor.get(IChatService);
await editingSession.redoInteraction();
widget.lastFocusedWidget?.viewModel?.model.setCheckpoint(undefined);
chatService.getSession(editingSession.chatSessionResource)?.setCheckpoint(undefined);
}
});
@@ -235,7 +236,7 @@ export function registerNewChatActions() {
await editingSession.redoInteraction();
}
const currentWidget = widget.lastFocusedWidget;
const currentWidget = widget.getWidgetBySessionResource(editingSession.chatSessionResource);
const requestText = currentWidget?.viewModel?.model.checkpoint?.message.text;
// if the input has the same text that we just restored, clear it.
@@ -29,7 +29,7 @@ import { ILabelService } from '../../../../../platform/label/common/label.js';
import { IResourceLabel, ResourceLabels } from '../../../../browser/labels.js';
import { ResourceContextKey } from '../../../../common/contextkeys.js';
import { IChatRequestImplicitVariableEntry, IChatRequestStringVariableEntry, isStringImplicitContextValue } from '../../common/chatVariableEntries.js';
import { IChatWidgetService } from '../chat.js';
import { IChatWidget } from '../chat.js';
import { ChatAttachmentModel } from '../chatAttachmentModel.js';
import { IChatContextService } from '../chatContextService.js';
@@ -39,6 +39,7 @@ export class ImplicitContextAttachmentWidget extends Disposable {
private readonly renderDisposables = this._register(new DisposableStore());
constructor(
private readonly widgetRef: () => IChatWidget | undefined,
private readonly attachment: IChatRequestImplicitVariableEntry,
private readonly resourceLabels: ResourceLabels,
private readonly attachmentModel: ChatAttachmentModel,
@@ -50,7 +51,6 @@ export class ImplicitContextAttachmentWidget extends Disposable {
@ILanguageService private readonly languageService: ILanguageService,
@IModelService private readonly modelService: IModelService,
@IHoverService private readonly hoverService: IHoverService,
@IChatWidgetService private readonly chatWidgetService: IChatWidgetService,
@IConfigurationService private readonly configService: IConfigurationService,
@IChatContextService private readonly chatContextService: IChatContextService,
) {
@@ -205,6 +205,6 @@ export class ImplicitContextAttachmentWidget extends Disposable {
const file = URI.isUri(this.attachment.value) ? this.attachment.value : this.attachment.value.uri;
this.attachmentModel.addFile(file);
}
this.chatWidgetService.lastFocusedWidget?.focusInput();
this.widgetRef()?.focusInput();
}
}
@@ -1065,7 +1065,7 @@ class ChatSlashStaticSlashCommandsContribution extends Disposable {
executeImmediately: true,
locations: [ChatAgentLocation.Chat],
modes: [ChatModeKind.Ask]
}, async (prompt, progress) => {
}, async (prompt, progress, _history, _location, sessionResource) => {
const defaultAgent = chatAgentService.getDefaultAgent(ChatAgentLocation.Chat);
const agents = chatAgentService.getAgents();
@@ -1085,11 +1085,11 @@ class ChatSlashStaticSlashCommandsContribution extends Disposable {
.filter(a => a.locations.includes(ChatAgentLocation.Chat))
.map(async a => {
const description = a.description ? `- ${a.description}` : '';
const agentMarkdown = instantiationService.invokeFunction(accessor => agentToMarkdown(a, true, accessor));
const agentMarkdown = instantiationService.invokeFunction(accessor => agentToMarkdown(a, sessionResource, true, accessor));
const agentLine = `- ${agentMarkdown} ${description}`;
const commandText = a.slashCommands.map(c => {
const description = c.description ? `- ${c.description}` : '';
return `\t* ${agentSlashCommandToMarkdown(a, c)} ${description}`;
return `\t* ${agentSlashCommandToMarkdown(a, c, sessionResource)} ${description}`;
}).join('\n');
return (agentLine + '\n' + commandText).trim();
@@ -36,6 +36,10 @@ export interface IChatWidgetService {
/**
* Returns the most recently focused widget if any.
*
* ⚠️ Consider carefully if this is appropriate for your use case. If you
* can know what session you're interacting with, prefer {@link getWidgetBySessionResource}
* or similar methods to work nicely with multiple chat widgets.
*/
readonly lastFocusedWidget: IChatWidget | undefined;
@@ -19,13 +19,13 @@ import { ILogService } from '../../../../platform/log/common/log.js';
import { IThemeService, Themable } from '../../../../platform/theme/common/themeService.js';
import { ISharedWebContentExtractorService } from '../../../../platform/webContentExtractor/common/webContentExtractor.js';
import { IExtensionService, isProposedApiEnabled } from '../../../services/extensions/common/extensions.js';
import { extractSCMHistoryItemDropData } from '../../scm/browser/scmHistoryChatContext.js';
import { IChatRequestVariableEntry } from '../common/chatVariableEntries.js';
import { IChatWidgetService } from './chat.js';
import { IChatAttachmentResolveService, ImageTransferData } from './chatAttachmentResolveService.js';
import { IChatWidget } from './chat.js';
import { ChatAttachmentModel } from './chatAttachmentModel.js';
import { IChatAttachmentResolveService, ImageTransferData } from './chatAttachmentResolveService.js';
import { IChatInputStyles } from './chatInputPart.js';
import { convertStringToUInt8Array } from './imageUtils.js';
import { extractSCMHistoryItemDropData } from '../../scm/browser/scmHistoryChatContext.js';
enum ChatDragAndDropType {
FILE_INTERNAL,
@@ -50,12 +50,12 @@ export class ChatDragAndDrop extends Themable {
private disableOverlay: boolean = false;
constructor(
private readonly widgetRef: () => IChatWidget | undefined,
private readonly attachmentModel: ChatAttachmentModel,
private readonly styles: IChatInputStyles,
@IThemeService themeService: IThemeService,
@IExtensionService private readonly extensionService: IExtensionService,
@ISharedWebContentExtractorService private readonly webContentExtractorService: ISharedWebContentExtractorService,
@IChatWidgetService private readonly chatWidgetService: IChatWidgetService,
@ILogService private readonly logService: ILogService,
@IChatAttachmentResolveService private readonly chatAttachmentResolveService: IChatAttachmentResolveService
) {
@@ -299,9 +299,10 @@ export class ChatDragAndDrop extends Themable {
}
// TODO: use dnd provider to insert text @justschen
const selection = this.chatWidgetService.lastFocusedWidget?.inputEditor.getSelection();
if (selection && this.chatWidgetService.lastFocusedWidget) {
this.chatWidgetService.lastFocusedWidget.inputEditor.executeEdits('chatInsertUrl', [{ range: selection, text: url }]);
const widget = this.widgetRef();
const selection = widget?.inputEditor.getSelection();
if (selection && widget) {
widget.inputEditor.executeEdits('chatInsertUrl', [{ range: selection, text: url }]);
}
this.logService.warn(`Image URLs must end in .jpg, .png, .gif, .webp, or .bmp. Failed to fetch image from this URL: ${url}`);
@@ -30,7 +30,7 @@ import { isChatViewTitleActionContext } from '../../common/chatActions.js';
import { ChatContextKeys } from '../../common/chatContextKeys.js';
import { applyingChatEditsFailedContextKey, CHAT_EDITING_MULTI_DIFF_SOURCE_RESOLVER_SCHEME, chatEditingResourceContextKey, chatEditingWidgetFileStateContextKey, decidedChatEditingResourceContextKey, hasAppliedChatEditsContextKey, hasUndecidedChatEditingResourceContextKey, IChatEditingService, IChatEditingSession, ModifiedFileEntryState } from '../../common/chatEditingService.js';
import { IChatService } from '../../common/chatService.js';
import { isRequestVM, isResponseVM } from '../../common/chatViewModel.js';
import { isChatTreeItem, isRequestVM, isResponseVM } from '../../common/chatViewModel.js';
import { ChatAgentLocation, ChatConfiguration, ChatModeKind } from '../../common/constants.js';
import { CHAT_CATEGORY } from '../actions/chatActions.js';
import { ChatTreeItem, IChatWidget, IChatWidgetService } from '../chat.js';
@@ -305,7 +305,7 @@ async function restoreSnapshotWithConfirmation(accessor: ServicesAccessor, item:
const configurationService = accessor.get(IConfigurationService);
const dialogService = accessor.get(IDialogService);
const chatWidgetService = accessor.get(IChatWidgetService);
const widget = chatWidgetService.lastFocusedWidget;
const widget = chatWidgetService.getWidgetBySessionResource(item.sessionResource);
const chatService = accessor.get(IChatService);
const chatModel = chatService.getSession(item.sessionResource);
if (!chatModel) {
@@ -403,7 +403,7 @@ registerAction2(class RemoveAction extends Action2 {
let item = args[0] as ChatTreeItem | undefined;
const chatWidgetService = accessor.get(IChatWidgetService);
const configurationService = accessor.get(IConfigurationService);
const widget = chatWidgetService.lastFocusedWidget;
const widget = (isChatTreeItem(item) && chatWidgetService.getWidgetBySessionResource(item.sessionResource)) || chatWidgetService.lastFocusedWidget;
if (!isResponseVM(item) && !isRequestVM(item)) {
item = widget?.getFocus();
}
@@ -451,7 +451,7 @@ registerAction2(class RestoreCheckpointAction extends Action2 {
async run(accessor: ServicesAccessor, ...args: unknown[]) {
let item = args[0] as ChatTreeItem | undefined;
const chatWidgetService = accessor.get(IChatWidgetService);
const widget = chatWidgetService.lastFocusedWidget;
const widget = (isChatTreeItem(item) && chatWidgetService.getWidgetBySessionResource(item.sessionResource)) || chatWidgetService.lastFocusedWidget;
if (!isResponseVM(item) && !isRequestVM(item)) {
item = widget?.getFocus();
}
@@ -493,7 +493,7 @@ registerAction2(class RestoreLastCheckpoint extends Action2 {
let item = args[0] as ChatTreeItem | undefined;
const chatWidgetService = accessor.get(IChatWidgetService);
const chatService = accessor.get(IChatService);
const widget = chatWidgetService.lastFocusedWidget;
const widget = (isChatTreeItem(item) && chatWidgetService.getWidgetBySessionResource(item.sessionResource)) || chatWidgetService.lastFocusedWidget;
if (!isResponseVM(item) && !isRequestVM(item)) {
item = widget?.getFocus();
}
@@ -552,7 +552,7 @@ registerAction2(class EditAction extends Action2 {
async run(accessor: ServicesAccessor, ...args: unknown[]) {
let item = args[0] as ChatTreeItem | undefined;
const chatWidgetService = accessor.get(IChatWidgetService);
const widget = chatWidgetService.lastFocusedWidget;
const widget = (isChatTreeItem(item) && chatWidgetService.getWidgetBySessionResource(item.sessionResource)) || chatWidgetService.lastFocusedWidget;
if (!isResponseVM(item) && !isRequestVM(item)) {
item = widget?.getFocus();
}
@@ -434,7 +434,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
this._attachmentModel = this._register(this.instantiationService.createInstance(ChatAttachmentModel));
this._register(this._attachmentModel.onDidChange(() => this._syncInputStateToModel()));
this.selectedToolsModel = this._register(this.instantiationService.createInstance(ChatSelectedTools, this.currentModeObs));
this.dnd = this._register(this.instantiationService.createInstance(ChatDragAndDrop, this._attachmentModel, styles));
this.dnd = this._register(this.instantiationService.createInstance(ChatDragAndDrop, () => this._widget, this._attachmentModel, styles));
this.inputEditorMaxHeight = this.options.renderStyle === 'compact' ? INPUT_EDITOR_MAX_HEIGHT / 3 : INPUT_EDITOR_MAX_HEIGHT;
@@ -1675,7 +1675,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
const isSuggestedEnabled = this.configurationService.getValue<boolean>('chat.implicitContext.suggestedContext');
if (this.implicitContext?.value && !isSuggestedEnabled) {
const implicitPart = store.add(this.instantiationService.createInstance(ImplicitContextAttachmentWidget, this.implicitContext, this._contextResourceLabels, this.attachmentModel));
const implicitPart = store.add(this.instantiationService.createInstance(ImplicitContextAttachmentWidget, () => this._widget, this.implicitContext, this._contextResourceLabels, this.attachmentModel));
container.appendChild(implicitPart.domNode);
}
@@ -1749,7 +1749,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
const shouldShowImplicit = !isLocation(implicitValue) ? !currentlyAttached : implicitValue.range;
if (shouldShowImplicit) {
const implicitPart = store.add(this.instantiationService.createInstance(ImplicitContextAttachmentWidget, this.implicitContext, this._contextResourceLabels, this._attachmentModel));
const implicitPart = store.add(this.instantiationService.createInstance(ImplicitContextAttachmentWidget, () => this._widget, this.implicitContext, this._contextResourceLabels, this._attachmentModel));
container.appendChild(implicitPart.domNode);
}
}
@@ -840,7 +840,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
if (!element.confirmation) {
const markdown = isChatFollowup(element.message) ?
element.message.message :
this.markdownDecorationsRenderer.convertParsedRequestToMarkdown(element.message);
this.markdownDecorationsRenderer.convertParsedRequestToMarkdown(element.sessionResource, element.message);
content = [{ content: new MarkdownString(markdown), kind: 'markdownContent' }];
if (this.rendererOptions.renderStyle === 'minimal' && !element.isComplete) {
@@ -38,7 +38,7 @@ const agentRefUrl = `http://_chatagent_`;
/** For rendering agent decorations with hover */
const agentSlashRefUrl = `http://_chatslash_`;
export function agentToMarkdown(agent: IChatAgentData, isClickable: boolean, accessor: ServicesAccessor): string {
export function agentToMarkdown(agent: IChatAgentData, sessionResource: URI, isClickable: boolean, accessor: ServicesAccessor): string {
const chatAgentNameService = accessor.get(IChatAgentNameService);
const chatAgentService = accessor.get(IChatAgentService);
@@ -49,25 +49,27 @@ export function agentToMarkdown(agent: IChatAgentData, isClickable: boolean, acc
name += ` (${agent.publisherDisplayName})`;
}
const args: IAgentWidgetArgs = { agentId: agent.id, name, isClickable };
const args: IAgentWidgetArgs = { agentId: agent.id, sessionResource, name, isClickable };
return `[${agent.name}](${agentRefUrl}?${encodeURIComponent(JSON.stringify(args))})`;
}
interface IAgentWidgetArgs {
sessionResource: URI;
agentId: string;
name: string;
isClickable?: boolean;
}
export function agentSlashCommandToMarkdown(agent: IChatAgentData, command: IChatAgentCommand): string {
export function agentSlashCommandToMarkdown(agent: IChatAgentData, command: IChatAgentCommand, sessionResource: URI): string {
const text = `${chatSubcommandLeader}${command.name}`;
const args: ISlashCommandWidgetArgs = { agentId: agent.id, command: command.name };
const args: ISlashCommandWidgetArgs = { agentId: agent.id, command: command.name, sessionResource };
return `[${text}](${agentSlashRefUrl}?${encodeURIComponent(JSON.stringify(args))})`;
}
interface ISlashCommandWidgetArgs {
agentId: string;
command: string;
sessionResource: URI;
}
export interface IDecorationWidgetArgs {
@@ -90,13 +92,13 @@ export class ChatMarkdownDecorationsRenderer {
@IChatMarkdownAnchorService private readonly chatMarkdownAnchorService: IChatMarkdownAnchorService,
) { }
convertParsedRequestToMarkdown(parsedRequest: IParsedChatRequest): string {
convertParsedRequestToMarkdown(sessionResource: URI, parsedRequest: IParsedChatRequest): string {
let result = '';
for (const part of parsedRequest.parts) {
if (part instanceof ChatRequestTextPart) {
result += part.text;
} else if (part instanceof ChatRequestAgentPart) {
result += this.instantiationService.invokeFunction(accessor => agentToMarkdown(part.agent, false, accessor));
result += this.instantiationService.invokeFunction(accessor => agentToMarkdown(part.agent, sessionResource, false, accessor));
} else {
result += this.genericDecorationToMarkdown(part);
}
@@ -180,7 +182,7 @@ export class ChatMarkdownDecorationsRenderer {
button.label = nameWithLeader;
store.add(button.onDidClick(() => {
const agent = this.chatAgentService.getAgent(args.agentId);
const widget = this.chatWidgetService.lastFocusedWidget;
const widget = this.chatWidgetService.getWidgetBySessionResource(args.sessionResource) || this.chatWidgetService.lastFocusedWidget;
if (!widget || !agent) {
return;
}
@@ -216,7 +218,7 @@ export class ChatMarkdownDecorationsRenderer {
}));
button.label = name;
store.add(button.onDidClick(() => {
const widget = this.chatWidgetService.lastFocusedWidget;
const widget = this.chatWidgetService.getWidgetBySessionResource(args.sessionResource) || this.chatWidgetService.lastFocusedWidget;
if (!widget || !agent) {
return;
}
@@ -605,7 +605,7 @@ class StartParameterizedPromptAction extends Action2 {
const widgetService = accessor.get(IChatWidgetService);
const fileService = accessor.get(IFileService);
const chatWidget = widgetService.lastFocusedWidget;
const chatWidget = await widgetService.revealWidget(true);
if (!chatWidget) {
return;
}
@@ -1135,7 +1135,7 @@ export class ChatService extends Disposable implements IChatService {
const message = parsedRequest.text;
const commandResult = await this.chatSlashCommandService.executeCommand(commandPart.slashCommand.command, message.substring(commandPart.slashCommand.command.length + 1).trimStart(), new Progress<IChatProgress>(p => {
progressCallback([p]);
}), history, location, token);
}), history, location, model.sessionResource, token);
agentOrCommandFollowups = Promise.resolve(commandResult?.followUp);
rawResult = {};
@@ -12,6 +12,7 @@ import { IChatMessage } from './languageModels.js';
import { IChatFollowup, IChatProgress, IChatResponseProgressFileTreeData } from './chatService.js';
import { IExtensionService } from '../../../services/extensions/common/extensions.js';
import { ChatAgentLocation, ChatModeKind } from './constants.js';
import { URI } from '../../../../base/common/uri.js';
//#region slash service, commands etc
@@ -41,7 +42,7 @@ export interface IChatSlashData {
export interface IChatSlashFragment {
content: string | { treeData: IChatResponseProgressFileTreeData };
}
export type IChatSlashCallback = { (prompt: string, progress: IProgress<IChatProgress>, history: IChatMessage[], location: ChatAgentLocation, token: CancellationToken): Promise<{ followUp: IChatFollowup[] } | void> };
export type IChatSlashCallback = { (prompt: string, progress: IProgress<IChatProgress>, history: IChatMessage[], location: ChatAgentLocation, sessionResource: URI, token: CancellationToken): Promise<{ followUp: IChatFollowup[] } | void> };
export const IChatSlashCommandService = createDecorator<IChatSlashCommandService>('chatSlashCommandService');
@@ -52,7 +53,7 @@ export interface IChatSlashCommandService {
_serviceBrand: undefined;
readonly onDidChangeCommands: Event<void>;
registerSlashCommand(data: IChatSlashData, command: IChatSlashCallback): IDisposable;
executeCommand(id: string, prompt: string, progress: IProgress<IChatProgress>, history: IChatMessage[], location: ChatAgentLocation, token: CancellationToken): Promise<{ followUp: IChatFollowup[] } | void>;
executeCommand(id: string, prompt: string, progress: IProgress<IChatProgress>, history: IChatMessage[], location: ChatAgentLocation, sessionResource: URI, token: CancellationToken): Promise<{ followUp: IChatFollowup[] } | void>;
getCommands(location: ChatAgentLocation, mode: ChatModeKind): Array<IChatSlashData>;
hasCommand(id: string): boolean;
}
@@ -102,7 +103,7 @@ export class ChatSlashCommandService extends Disposable implements IChatSlashCom
return this._commands.has(id);
}
async executeCommand(id: string, prompt: string, progress: IProgress<IChatProgress>, history: IChatMessage[], location: ChatAgentLocation, token: CancellationToken): Promise<{ followUp: IChatFollowup[] } | void> {
async executeCommand(id: string, prompt: string, progress: IProgress<IChatProgress>, history: IChatMessage[], location: ChatAgentLocation, sessionResource: URI, token: CancellationToken): Promise<{ followUp: IChatFollowup[] } | void> {
const data = this._commands.get(id);
if (!data) {
throw new Error('No command with id ${id} NOT registered');
@@ -114,6 +115,6 @@ export class ChatSlashCommandService extends Disposable implements IChatSlashCom
throw new Error(`No command with id ${id} NOT resolved`);
}
return await data.command(prompt, progress, history, location, token);
return await data.command(prompt, progress, history, location, sessionResource, token);
}
}
@@ -310,7 +310,7 @@ class KernelVariableContextPicker implements IChatContextPickerItem {
}
registerAction2(class CopyCellOutputAction extends Action2 {
registerAction2(class AddCellOutputToChatAction extends Action2 {
constructor() {
super({
id: 'notebook.cellOutput.addToChat',
@@ -371,15 +371,8 @@ registerAction2(class CopyCellOutputAction extends Action2 {
const mimeType = outputViewModel.pickedMimeType?.mimeType;
const chatWidgetService = accessor.get(IChatWidgetService);
let widget = chatWidgetService.lastFocusedWidget;
if (!widget) {
const widgets = chatWidgetService.getWidgetsByLocations(ChatAgentLocation.Chat);
if (widgets.length === 0) {
return;
}
widget = widgets[0];
}
if (mimeType && NOTEBOOK_CELL_OUTPUT_MIME_TYPE_LIST_FOR_CHAT_CONST.includes(mimeType)) {
const widget = await chatWidgetService.revealWidget();
if (widget && mimeType && NOTEBOOK_CELL_OUTPUT_MIME_TYPE_LIST_FOR_CHAT_CONST.includes(mimeType)) {
const entry = createNotebookOutputVariableEntry(outputViewModel, mimeType, notebookEditor);
if (!entry) {