mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-30 15:04:28 +01:00
chat: cleanup most flagrant usages of IChatWidgetService.lastFocusedWidget (#278861)
Closes https://github.com/microsoft/vscode/issues/278638 mostly
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-10
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user