adding title for fetched resources content display (#283742)

* adding title for fetched resources content display

* adding title for fetched resources content display
This commit is contained in:
dileepyavan
2025-12-16 11:12:26 -08:00
committed by GitHub
parent 1d9de1a9d8
commit aeb743289b
5 changed files with 32 additions and 9 deletions

View File

@@ -33,6 +33,7 @@ export interface IChatCollapsibleIOCodePart {
languageId: string; languageId: string;
options: ICodeBlockRenderOptions; options: ICodeBlockRenderOptions;
codeBlockInfo: IChatCodeBlockInfo; codeBlockInfo: IChatCodeBlockInfo;
title?: string | IMarkdownString;
} }
export interface IChatCollapsibleIODataPart { export interface IChatCollapsibleIODataPart {

View File

@@ -25,6 +25,8 @@ import { IProgressService, ProgressLocation } from '../../../../../platform/prog
import { IWorkspaceContextService } from '../../../../../platform/workspace/common/workspace.js'; import { IWorkspaceContextService } from '../../../../../platform/workspace/common/workspace.js';
import { REVEAL_IN_EXPLORER_COMMAND_ID } from '../../../files/browser/fileConstants.js'; import { REVEAL_IN_EXPLORER_COMMAND_ID } from '../../../files/browser/fileConstants.js';
import { getAttachableImageExtension } from '../../common/chatModel.js'; import { getAttachableImageExtension } from '../../common/chatModel.js';
import { IMarkdownString, MarkdownString } from '../../../../../base/common/htmlContent.js';
import { IMarkdownRendererService } from '../../../../../platform/markdown/browser/markdownRenderer.js';
import { IChatRequestVariableEntry } from '../../common/chatVariableEntries.js'; import { IChatRequestVariableEntry } from '../../common/chatVariableEntries.js';
import { IChatCodeBlockInfo } from '../chat.js'; import { IChatCodeBlockInfo } from '../chat.js';
import { CodeBlockPart, ICodeBlockData } from '../codeBlockPart.js'; import { CodeBlockPart, ICodeBlockData } from '../codeBlockPart.js';
@@ -44,22 +46,29 @@ export class ChatToolOutputContentSubPart extends Disposable {
private _currentWidth: number = 0; private _currentWidth: number = 0;
private readonly _editorReferences: IDisposableReference<CodeBlockPart>[] = []; private readonly _editorReferences: IDisposableReference<CodeBlockPart>[] = [];
public readonly domNode: HTMLElement; public readonly domNode: HTMLElement;
readonly codeblocks: IChatCodeBlockInfo[] = []; readonly codeblocks: IChatCodeBlockInfo[] = [];
constructor( constructor(
private readonly context: IChatContentPartRenderContext, private readonly context: IChatContentPartRenderContext,
private readonly parts: ChatCollapsibleIOPart[], private readonly parts: ChatCollapsibleIOPart[],
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IInstantiationService private readonly _instantiationService: IInstantiationService, @IInstantiationService private readonly _instantiationService: IInstantiationService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IContextMenuService private readonly _contextMenuService: IContextMenuService, @IContextMenuService private readonly _contextMenuService: IContextMenuService,
@IFileService private readonly _fileService: IFileService, @IFileService private readonly _fileService: IFileService,
@IMarkdownRendererService private readonly _markdownRendererService: IMarkdownRendererService,
) { ) {
super(); super();
this.domNode = this.createOutputContents(); this.domNode = this.createOutputContents();
this._currentWidth = context.currentWidth(); this._currentWidth = context.currentWidth();
} }
private toMdString(value: string | IMarkdownString): MarkdownString {
if (typeof value === 'string') {
return new MarkdownString('').appendText(value);
}
return new MarkdownString(value.value, { isTrusted: value.isTrusted });
}
private createOutputContents(): HTMLElement { private createOutputContents(): HTMLElement {
const container = dom.$('div'); const container = dom.$('div');
@@ -145,6 +154,13 @@ export class ChatToolOutputContentSubPart extends Disposable {
} }
private addCodeBlock(part: IChatCollapsibleIOCodePart, container: HTMLElement) { private addCodeBlock(part: IChatCollapsibleIOCodePart, container: HTMLElement) {
if (part.title) {
const title = dom.$('div.chat-confirmation-widget-title');
const renderedTitle = this._register(this._markdownRendererService.render(this.toMdString(part.title)));
title.appendChild(renderedTitle.element);
container.appendChild(title);
}
const data: ICodeBlockData = { const data: ICodeBlockData = {
languageId: part.languageId, languageId: part.languageId,
textModel: Promise.resolve(part.textModel), textModel: Promise.resolve(part.textModel),

View File

@@ -120,6 +120,7 @@ export class ChatToolPostExecuteConfirmationPart extends AbstractToolConfirmatio
parts.push({ parts.push({
kind: 'code', kind: 'code',
title: part.title,
textModel: model, textModel: model,
languageId: model.getLanguageId(), languageId: model.getLanguageId(),
options: { options: {

View File

@@ -240,6 +240,7 @@ export interface IToolResultTextPart {
kind: 'text'; kind: 'text';
value: string; value: string;
audience?: LanguageModelPartAudience[]; audience?: LanguageModelPartAudience[];
title?: string;
} }
export interface IToolResultDataPart { export interface IToolResultDataPart {
@@ -249,6 +250,7 @@ export interface IToolResultDataPart {
data: VSBuffer; data: VSBuffer;
}; };
audience?: LanguageModelPartAudience[]; audience?: LanguageModelPartAudience[];
title?: string;
} }
export interface IToolConfirmationMessages { export interface IToolConfirmationMessages {

View File

@@ -144,7 +144,7 @@ export class FetchWebPageTool implements IToolImpl {
const actuallyValidUris = [...webUris.values(), ...successfulFileUris]; const actuallyValidUris = [...webUris.values(), ...successfulFileUris];
return { return {
content: this._getPromptPartsForResults(results), content: this._getPromptPartsForResults(urls, results),
toolResultDetails: actuallyValidUris, toolResultDetails: actuallyValidUris,
confirmResults, confirmResults,
}; };
@@ -278,28 +278,31 @@ export class FetchWebPageTool implements IToolImpl {
return { webUris, fileUris, invalidUris }; return { webUris, fileUris, invalidUris };
} }
private _getPromptPartsForResults(results: ResultType[]): (IToolResultTextPart | IToolResultDataPart)[] { private _getPromptPartsForResults(urls: string[], results: ResultType[]): (IToolResultTextPart | IToolResultDataPart)[] {
return results.map(value => { return results.map((value, i) => {
const title = results.length > 1 ? localize('fetchWebPage.fetchedFrom', 'Fetched from {0}', urls[i]) : undefined;
if (!value) { if (!value) {
return { return {
kind: 'text', kind: 'text',
title,
value: localize('fetchWebPage.invalidUrl', 'Invalid URL') value: localize('fetchWebPage.invalidUrl', 'Invalid URL')
}; };
} else if (typeof value === 'string') { } else if (typeof value === 'string') {
return { return {
kind: 'text', kind: 'text',
title,
value: value value: value
}; };
} else if (value.type === 'tooldata') { } else if (value.type === 'tooldata') {
return value.value; return { ...value.value, title };
} else if (value.type === 'extracted') { } else if (value.type === 'extracted') {
switch (value.value.status) { switch (value.value.status) {
case 'ok': case 'ok':
return { kind: 'text', value: value.value.result }; return { kind: 'text', title, value: value.value.result };
case 'redirect': case 'redirect':
return { kind: 'text', value: `The webpage has redirected to "${value.value.toURI.toString(true)}". Use the ${InternalFetchWebPageToolId} again to get its contents.` }; return { kind: 'text', title, value: `The webpage has redirected to "${value.value.toURI.toString(true)}". Use the ${InternalFetchWebPageToolId} again to get its contents.` };
case 'error': case 'error':
return { kind: 'text', value: `An error occurred retrieving the fetch result: ${value.value.error}` }; return { kind: 'text', title, value: `An error occurred retrieving the fetch result: ${value.value.error}` };
default: default:
assertNever(value.value); assertNever(value.value);
} }