diff --git a/src/@types/vscode.proposed.chatParticipantAdditions.d.ts b/src/@types/vscode.proposed.chatParticipantAdditions.d.ts index 71520fa1ec..aa7001a3d2 100644 --- a/src/@types/vscode.proposed.chatParticipantAdditions.d.ts +++ b/src/@types/vscode.proposed.chatParticipantAdditions.d.ts @@ -105,6 +105,7 @@ declare module 'vscode' { isComplete?: boolean; toolSpecificData?: ChatTerminalToolInvocationData; fromSubAgent?: boolean; + presentation?: 'hidden' | 'hiddenAfterComplete' | undefined; constructor(toolName: string, toolCallId: string, isError?: boolean); } diff --git a/src/@types/vscode.proposed.chatSessionsProvider.d.ts b/src/@types/vscode.proposed.chatSessionsProvider.d.ts index bd4e624430..772fc387b9 100644 --- a/src/@types/vscode.proposed.chatSessionsProvider.d.ts +++ b/src/@types/vscode.proposed.chatSessionsProvider.d.ts @@ -95,6 +95,11 @@ declare module 'vscode' { */ description?: string | MarkdownString; + /** + * An optional badge that provides additional context about the chat session. + */ + badge?: string | MarkdownString; + /** * An optional status indicating the current state of the session. */ diff --git a/src/lm/tools/fetchIssueTool.ts b/src/lm/tools/fetchIssueTool.ts index e63b81b9b9..ecafaa4e74 100644 --- a/src/lm/tools/fetchIssueTool.ts +++ b/src/lm/tools/fetchIssueTool.ts @@ -36,6 +36,8 @@ export interface FetchIssueResult { author?: string; assignees?: string[]; reviewers?: string[]; + issueNumber?: number; + itemType?: 'issue' | 'pr'; } export class FetchIssueTool extends RepoToolBase { @@ -51,6 +53,7 @@ export class FetchIssueTool extends RepoToolBase { if (!issueOrPullRequest) { throw new Error(`No issue or pull request found for ${owner}/${name}/${issueNumber}. Make sure the issue or pull request exists.`); } + const itemType = issueOrPullRequest instanceof PullRequestModel ? 'pr' : 'issue'; const result: FetchIssueResult = { owner, repo: name, @@ -59,7 +62,9 @@ export class FetchIssueTool extends RepoToolBase { comments: issueOrPullRequest.item.comments?.map(c => ({ body: c.body, author: c.author.login })) ?? [], author: issueOrPullRequest.author?.login, assignees: issueOrPullRequest.assignees?.map(a => a.login), - reviewers: issueOrPullRequest instanceof PullRequestModel ? issueOrPullRequest.reviewers?.map(r => isITeam(r) ? r.name : r.login).filter((login): login is string => !!login) : undefined + reviewers: issueOrPullRequest instanceof PullRequestModel ? issueOrPullRequest.reviewers?.map(r => isITeam(r) ? r.name : r.login).filter((login): login is string => !!login) : undefined, + issueNumber, + itemType }; if (issueOrPullRequest instanceof PullRequestModel && issueOrPullRequest.isResolved()) { const fileChanges = await issueOrPullRequest.getFileChangesInfo(); diff --git a/src/lm/tools/summarizeIssueTool.ts b/src/lm/tools/summarizeIssueTool.ts index a0c6fb71d8..1da58d7587 100644 --- a/src/lm/tools/summarizeIssueTool.ts +++ b/src/lm/tools/summarizeIssueTool.ts @@ -6,7 +6,8 @@ import * as vscode from 'vscode'; import { FetchIssueResult } from './fetchIssueTool'; -import { concatAsyncIterable } from './toolsUtils'; +import { concatAsyncIterable, TOOL_COMMAND_RESULT } from './toolsUtils'; +import { toOpenIssueWebviewUri, toOpenPullRequestWebviewUri } from '../../common/uri'; export class IssueSummarizationTool implements vscode.LanguageModelTool { public static readonly toolId = 'github-pull-request_issue_summarize'; @@ -58,6 +59,23 @@ Body: ${comment.body} const model = models[0]; const repo = options.input.repo; const owner = options.input.owner; + const content: vscode.LanguageModelTextPart[] = []; + + // Add Open command if we have the necessary information + const issueNumber = options.input.issueNumber; + const itemType = options.input.itemType; + if (owner && repo && issueNumber && itemType) { + const uri = itemType === 'issue' + ? await toOpenIssueWebviewUri({ owner, repo, issueNumber }) + : await toOpenPullRequestWebviewUri({ owner, repo, pullRequestNumber: issueNumber }); + const openCommand: vscode.Command = { + title: 'Open', + command: 'vscode.open', + arguments: [uri] + }; + content.push(new vscode.LanguageModelTextPart(TOOL_COMMAND_RESULT)); + content.push(new vscode.LanguageModelTextPart(JSON.stringify(openCommand))); + } if (model && repo && owner) { const messages = [vscode.LanguageModelChatMessage.User(this.summarizeInstructions(repo, owner))]; @@ -65,10 +83,11 @@ Body: ${comment.body} messages.push(vscode.LanguageModelChatMessage.User(issueOrPullRequestInfo)); const response = await model.sendRequest(messages, {}); const responseText = await concatAsyncIterable(response.text); - return new vscode.LanguageModelToolResult([new vscode.LanguageModelTextPart(responseText)]); + content.push(new vscode.LanguageModelTextPart(responseText)); } else { - return new vscode.LanguageModelToolResult([new vscode.LanguageModelTextPart(issueOrPullRequestInfo)]); + content.push(new vscode.LanguageModelTextPart(issueOrPullRequestInfo)); } + return new vscode.LanguageModelToolResult(content); } private summarizeInstructions(repo: string, owner: string): string { diff --git a/src/lm/tools/summarizeNotificationsTool.ts b/src/lm/tools/summarizeNotificationsTool.ts index 7a4891f312..34e0574a27 100644 --- a/src/lm/tools/summarizeNotificationsTool.ts +++ b/src/lm/tools/summarizeNotificationsTool.ts @@ -7,6 +7,7 @@ import * as vscode from 'vscode'; import { FetchNotificationResult } from './fetchNotificationTool'; import { concatAsyncIterable, TOOL_COMMAND_RESULT } from './toolsUtils'; +import { toOpenIssueWebviewUri, toOpenPullRequestWebviewUri } from '../../common/uri'; export class NotificationSummarizationTool implements vscode.LanguageModelTool { public static readonly toolId = 'github-pull-request_notification_summarize'; @@ -70,6 +71,11 @@ Body: ${comment.body} const content: vscode.LanguageModelTextPart[] = []; const threadId = options.input.threadId; const notificationKey = options.input.notificationKey; + const owner = options.input.owner; + const repo = options.input.repo; + const itemNumber = options.input.itemNumber; + const itemType = options.input.itemType; + if (threadId && notificationKey) { const markAsReadCommand = { title: 'Mark As Read', @@ -85,9 +91,21 @@ Body: ${comment.body} content.push(new vscode.LanguageModelTextPart(JSON.stringify(markAsReadCommand))); content.push(new vscode.LanguageModelTextPart(TOOL_COMMAND_RESULT)); content.push(new vscode.LanguageModelTextPart(JSON.stringify(markAsDoneCommand))); + + // Add Open command + if (owner && repo && itemNumber && itemType) { + const uri = itemType === 'issue' + ? await toOpenIssueWebviewUri({ owner, repo, issueNumber: Number(itemNumber) }) + : await toOpenPullRequestWebviewUri({ owner, repo, pullRequestNumber: Number(itemNumber) }); + const openCommand: vscode.Command = { + title: 'Open', + command: 'vscode.open', + arguments: [uri] + }; + content.push(new vscode.LanguageModelTextPart(TOOL_COMMAND_RESULT)); + content.push(new vscode.LanguageModelTextPart(JSON.stringify(openCommand))); + } } - const owner = options.input.owner; - const repo = options.input.repo; if (model && owner && repo) { const messages = [vscode.LanguageModelChatMessage.User(this.summarizeInstructions(owner, repo))]; messages.push(vscode.LanguageModelChatMessage.User(`The notification information is as follows:`));