diff --git a/eslint.config.js b/eslint.config.js index 8af1bce892a..e3be2d2e218 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -266,8 +266,6 @@ export default tseslint.config( 'src/vs/workbench/browser/workbench.ts', 'src/vs/workbench/common/notifications.ts', 'src/vs/workbench/contrib/accessibility/browser/accessibleView.ts', - 'src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts', - 'src/vs/workbench/contrib/chat/browser/chat.ts', 'src/vs/workbench/contrib/chat/browser/chatAttachmentResolveService.ts', 'src/vs/workbench/contrib/chat/browser/chatContentParts/chatAttachmentsContentPart.ts', 'src/vs/workbench/contrib/chat/browser/chatContentParts/chatConfirmationWidget.ts', @@ -277,16 +275,11 @@ export default tseslint.config( 'src/vs/workbench/contrib/chat/browser/chatContentParts/toolInvocationParts/abstractToolConfirmationSubPart.ts', 'src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingSession.ts', 'src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingSessionStorage.ts', - 'src/vs/workbench/contrib/chat/browser/chatEditorInput.ts', - 'src/vs/workbench/contrib/chat/browser/chatFollowups.ts', 'src/vs/workbench/contrib/chat/browser/chatInlineAnchorWidget.ts', - 'src/vs/workbench/contrib/chat/browser/chatInputPart.ts', - 'src/vs/workbench/contrib/chat/browser/chatListRenderer.ts', 'src/vs/workbench/contrib/chat/browser/chatResponseAccessibleView.ts', 'src/vs/workbench/contrib/chat/browser/chatSessions/common.ts', 'src/vs/workbench/contrib/chat/browser/chatSessions/localChatSessionsProvider.ts', 'src/vs/workbench/contrib/chat/browser/chatSessions/view/sessionsTreeRenderer.ts', - 'src/vs/workbench/contrib/chat/browser/chatWidget.ts', 'src/vs/workbench/contrib/chat/browser/contrib/chatInputCompletions.ts', 'src/vs/workbench/contrib/chat/common/annotations.ts', 'src/vs/workbench/contrib/chat/common/chat.ts', diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts b/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts index 117d84e18d3..96d3eda8f36 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts @@ -45,6 +45,7 @@ import { getEditingSessionContext } from '../chatEditing/chatEditingActions.js'; import { ACTION_ID_NEW_CHAT, CHAT_CATEGORY, handleCurrentEditingSession, handleModeSwitch } from './chatActions.js'; import { ctxHasEditorModification } from '../chatEditing/chatEditingEditorContextKeys.js'; import { chatSessionResourceToId } from '../../common/chatUri.js'; +import { isITextModel } from '../../../../../editor/common/model.js'; export interface IVoiceChatExecuteActionContext { readonly disableTimeout?: boolean; @@ -822,7 +823,7 @@ export class CreateRemoteAgentJobAction extends Action2 { if (activeEditor) { const model = activeEditor.getModel(); let activeEditorUri: URI | undefined = undefined; - if (model && 'uri' in model) { + if (model && isITextModel(model)) { activeEditorUri = model.uri as URI; } const selection = activeEditor.getSelection(); diff --git a/src/vs/workbench/contrib/chat/browser/chat.ts b/src/vs/workbench/contrib/chat/browser/chat.ts index ef3cd80dee3..bbe78b7c869 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.ts @@ -56,7 +56,7 @@ export interface IChatWidgetService { } export async function showChatWidgetInViewOrEditor(accessor: ServicesAccessor, widget: IChatWidget) { - if ('viewId' in widget.viewContext) { + if (isIChatViewViewContext(widget.viewContext)) { await accessor.get(IViewsService).openView(widget.viewContext.viewId); } else { const sessionResource = widget.viewModel?.sessionResource; @@ -185,11 +185,19 @@ export interface IChatViewViewContext { viewId: string; } +export function isIChatViewViewContext(context: IChatWidgetViewContext): context is IChatViewViewContext { + return typeof (context as IChatViewViewContext).viewId === 'string'; +} + export interface IChatResourceViewContext { isQuickChat?: boolean; isInlineChat?: boolean; } +export function isIChatResourceViewContext(context: IChatWidgetViewContext): context is IChatResourceViewContext { + return !isIChatViewViewContext(context); +} + export type IChatWidgetViewContext = IChatViewViewContext | IChatResourceViewContext | {}; export interface IChatAcceptInputOptions { diff --git a/src/vs/workbench/contrib/chat/browser/chatEditorInput.ts b/src/vs/workbench/contrib/chat/browser/chatEditorInput.ts index bf9fcb14a89..1bbebee9f85 100644 --- a/src/vs/workbench/contrib/chat/browser/chatEditorInput.ts +++ b/src/vs/workbench/contrib/chat/browser/chatEditorInput.ts @@ -271,7 +271,7 @@ export class ChatEditorInput extends EditorInput implements IEditorCloseHandler ?? this.chatService.startSession(ChatAgentLocation.Chat, CancellationToken.None, undefined, { canUseTools: false }); } else if (!this.options.target) { this.model = this.chatService.startSession(ChatAgentLocation.Chat, CancellationToken.None, undefined, { canUseTools: !inputType }); - } else if ('data' in this.options.target) { + } else if (this.options.target.data) { this.model = this.chatService.loadSessionFromContent(this.options.target.data); } diff --git a/src/vs/workbench/contrib/chat/browser/chatFollowups.ts b/src/vs/workbench/contrib/chat/browser/chatFollowups.ts index f4d55df96e4..2c2bd77a0c6 100644 --- a/src/vs/workbench/contrib/chat/browser/chatFollowups.ts +++ b/src/vs/workbench/contrib/chat/browser/chatFollowups.ts @@ -47,7 +47,7 @@ export class ChatFollowups extends Disposable { : followup.title; const message = followup.kind === 'reply' ? followup.message : followup.title; const tooltip = (tooltipPrefix + - ('tooltip' in followup && followup.tooltip || message)).trim(); + (followup.tooltip || message)).trim(); const button = this._register(new Button(container, { ...this.options, title: tooltip })); if (followup.kind === 'reply') { button.element.classList.add('interactive-followup-reply'); diff --git a/src/vs/workbench/contrib/chat/browser/chatInputPart.ts b/src/vs/workbench/contrib/chat/browser/chatInputPart.ts index d7d71a24dda..4caa5ea693a 100644 --- a/src/vs/workbench/contrib/chat/browser/chatInputPart.ts +++ b/src/vs/workbench/contrib/chat/browser/chatInputPart.ts @@ -37,7 +37,6 @@ import { CodeEditorWidget } from '../../../../editor/browser/widget/codeEditor/c import { EditorOptions, IEditorOptions } from '../../../../editor/common/config/editorOptions.js'; import { IDimension } from '../../../../editor/common/core/2d/dimension.js'; import { IPosition } from '../../../../editor/common/core/position.js'; -import { Range } from '../../../../editor/common/core/range.js'; import { isLocation } from '../../../../editor/common/languages.js'; import { ITextModel } from '../../../../editor/common/model.js'; import { IModelService } from '../../../../editor/common/services/model.js'; @@ -1616,8 +1615,8 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge this.promptFileAttached.set(this.hasPromptFileAttachments); for (const [index, attachment] of attachments) { - const resource = URI.isUri(attachment.value) ? attachment.value : attachment.value && typeof attachment.value === 'object' && 'uri' in attachment.value && URI.isUri(attachment.value.uri) ? attachment.value.uri : undefined; - const range = attachment.value && typeof attachment.value === 'object' && 'range' in attachment.value && Range.isIRange(attachment.value.range) ? attachment.value.range : undefined; + const resource = URI.isUri(attachment.value) ? attachment.value : isLocation(attachment.value) ? attachment.value.uri : undefined; + const range = isLocation(attachment.value) ? attachment.value.range : undefined; const shouldFocusClearButton = index === Math.min(this._indexOfLastAttachedContextDeletedWithKeyboard, this.attachmentModel.size - 1) && this._indexOfLastAttachedContextDeletedWithKeyboard > -1; let attachmentWidget; diff --git a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts index 765f0018b0c..7ecf0160dce 100644 --- a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts +++ b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts @@ -53,7 +53,7 @@ import { IChatAgentMetadata } from '../common/chatAgents.js'; import { ChatContextKeys } from '../common/chatContextKeys.js'; import { IChatTextEditGroup } from '../common/chatModel.js'; import { chatSubcommandLeader } from '../common/chatParserTypes.js'; -import { ChatAgentVoteDirection, ChatAgentVoteDownReason, ChatErrorLevel, IChatChangesSummary, IChatConfirmation, IChatContentReference, IChatElicitationRequest, IChatExtensionsContent, IChatFollowup, IChatMarkdownContent, IChatMcpServersStarting, IChatMultiDiffData, IChatPullRequestContent, IChatTask, IChatTaskSerialized, IChatThinkingPart, IChatToolInvocation, IChatToolInvocationSerialized, IChatTreeData, IChatUndoStop } from '../common/chatService.js'; +import { ChatAgentVoteDirection, ChatAgentVoteDownReason, ChatErrorLevel, IChatChangesSummary, IChatConfirmation, IChatContentReference, IChatElicitationRequest, IChatExtensionsContent, IChatFollowup, IChatMarkdownContent, IChatMcpServersStarting, IChatMultiDiffData, IChatPullRequestContent, IChatTask, IChatTaskSerialized, IChatThinkingPart, IChatToolInvocation, IChatToolInvocationSerialized, IChatTreeData, IChatUndoStop, isChatFollowup } from '../common/chatService.js'; import { IChatRequestVariableEntry } from '../common/chatVariableEntries.js'; import { IChatChangesSummaryPart, IChatCodeCitations, IChatErrorDetailsPart, IChatReferences, IChatRendererContent, IChatRequestViewModel, IChatResponseViewModel, IChatViewModel, isRequestVM, isResponseVM } from '../common/chatViewModel.js'; import { getNWords } from '../common/chatWordCounter.js'; @@ -835,7 +835,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer { getHeight(element: ChatTreeItem): number { const kind = isRequestVM(element) ? 'request' : 'response'; - const height = ('currentRenderedHeight' in element ? element.currentRenderedHeight : undefined) ?? this.defaultElementHeight; + const height = element.currentRenderedHeight ?? this.defaultElementHeight; this._traceLayout('getHeight', `${kind}, height=${height}`); return height; } diff --git a/src/vs/workbench/contrib/chat/browser/chatWidget.ts b/src/vs/workbench/contrib/chat/browser/chatWidget.ts index c43cee531e5..d55fa80b899 100644 --- a/src/vs/workbench/contrib/chat/browser/chatWidget.ts +++ b/src/vs/workbench/contrib/chat/browser/chatWidget.ts @@ -84,7 +84,7 @@ import { PromptsType } from '../common/promptSyntax/promptTypes.js'; import { IHandOff, ParsedPromptFile, PromptHeader, Target } from '../common/promptSyntax/promptFileParser.js'; import { IPromptsService } from '../common/promptSyntax/service/promptsService.js'; import { handleModeSwitch } from './actions/chatActions.js'; -import { ChatTreeItem, ChatViewId, IChatAcceptInputOptions, IChatAccessibilityService, IChatCodeBlockInfo, IChatFileTreeInfo, IChatListItemRendererOptions, IChatWidget, IChatWidgetService, IChatWidgetViewContext, IChatWidgetViewOptions } from './chat.js'; +import { ChatTreeItem, ChatViewId, IChatAcceptInputOptions, IChatAccessibilityService, IChatCodeBlockInfo, IChatFileTreeInfo, IChatListItemRendererOptions, IChatWidget, IChatWidgetService, IChatWidgetViewContext, IChatWidgetViewOptions, isIChatResourceViewContext, isIChatViewViewContext } from './chat.js'; import { ChatAccessibilityProvider } from './chatAccessibilityProvider.js'; import { ChatAttachmentModel } from './chatAttachmentModel.js'; import { ChatSuggestNextWidget } from './chatContentParts/chatSuggestNextWidget.js'; @@ -140,11 +140,11 @@ export interface IChatWidgetLocationOptions { } export function isQuickChat(widget: IChatWidget): boolean { - return 'viewContext' in widget && 'isQuickChat' in widget.viewContext && Boolean(widget.viewContext.isQuickChat); + return isIChatResourceViewContext(widget.viewContext) && Boolean(widget.viewContext.isQuickChat); } export function isInlineChat(widget: IChatWidget): boolean { - return 'viewContext' in widget && 'isInlineChat' in widget.viewContext && Boolean(widget.viewContext.isInlineChat); + return isIChatResourceViewContext(widget.viewContext) && Boolean(widget.viewContext.isInlineChat); } interface IChatHistoryListItem { @@ -790,7 +790,7 @@ export class ChatWidget extends Disposable implements IChatWidget { } render(parent: HTMLElement): void { - const viewId = 'viewId' in this.viewContext ? this.viewContext.viewId : undefined; + const viewId = isIChatViewViewContext(this.viewContext) ? this.viewContext.viewId : undefined; this.editorOptions = this._register(this.instantiationService.createInstance(ChatEditorOptions, viewId, this.styles.listForeground, this.styles.inputEditorBackground, this.styles.resultEditorBackground)); const renderInputOnTop = this.viewOptions.renderInputOnTop ?? false; const renderFollowups = this.viewOptions.renderFollowups ?? !renderInputOnTop; @@ -2061,7 +2061,7 @@ export class ChatWidget extends Disposable implements IChatWidget { private getWidgetViewKindTag(): string { if (!this.viewContext) { return 'editor'; - } else if ('viewId' in this.viewContext) { + } else if (isIChatViewViewContext(this.viewContext)) { return 'view'; } else { return 'quick'; diff --git a/src/vs/workbench/contrib/chat/common/chatService.ts b/src/vs/workbench/contrib/chat/common/chatService.ts index a5d2c6bcc08..68677b268e8 100644 --- a/src/vs/workbench/contrib/chat/common/chatService.ts +++ b/src/vs/workbench/contrib/chat/common/chatService.ts @@ -672,6 +672,15 @@ export interface IChatFollowup { tooltip?: string; } +export function isChatFollowup(obj: unknown): obj is IChatFollowup { + return ( + !!obj && + (obj as IChatFollowup).kind === 'reply' && + typeof (obj as IChatFollowup).message === 'string' && + typeof (obj as IChatFollowup).agentId === 'string' + ); +} + export enum ChatAgentVoteDirection { Down = 0, Up = 1