mirror of
https://github.com/microsoft/vscode-extension-samples.git
synced 2026-04-27 16:55:44 +08:00
Adopt @vscode/chat-extension-utils (#1130)
* Adopt @vscode/chat-extension-utils * Update readme
This commit is contained in:
1
chat-sample/.vscode/settings.json
vendored
1
chat-sample/.vscode/settings.json
vendored
@ -5,4 +5,5 @@
|
||||
"git.branchProtection": [
|
||||
"main"
|
||||
],
|
||||
"files.trimTrailingWhitespace": true
|
||||
}
|
||||
@ -8,9 +8,10 @@ When an extension uses the Chat or the Language Model API, we call it a GitHub C
|
||||
|
||||
This GitHub Copilot Extension sample shows:
|
||||
|
||||
- How to contribute a simple chat participant to the GitHub Copilot Chat view.
|
||||
- How to use the Language Model API to request access to the Language Model (gpt-4o, gpt-3.5-turbo, gpt-4).
|
||||
- How to contribute a more sophisticated chat participant that uses the LanguageModelTool API to contribute and invoke tools.
|
||||
- How to contribute a simple chat participant to the GitHub Copilot Chat view. (`@cat`, [simple.ts](src/simple.ts))
|
||||
- How to use the Language Model API to request access to the Language Model.
|
||||
- How to use the `@vscode/chat-extension-utils` library to easily create a chat participant that uses tools. (`@catTools`, [chatUtilsSample.ts](src/chatUtilsSample.ts))
|
||||
- How to contribute a more sophisticated chat participant that uses the LanguageModelTool API to contribute and invoke tools. (`@tool`, [toolParticipant.ts](src/toolParticipant.ts))
|
||||
|
||||

|
||||
|
||||
@ -32,4 +33,4 @@ This sample shows two different ways to build a chat participant in VS Code:
|
||||
|
||||
See [simple.ts](src/simple.ts) for an example of a simple chat participant that makes requests and responds to user queries. It shows how you can create chat participants with or without the [@vscode/prompt-tsx](https://www.npmjs.com/package/@vscode/prompt-tsx) library.
|
||||
|
||||
See [toolParticipant.ts](src/toolParticipant.ts) for an example of a chat participant that invokes tools, either dynamically or using the `toolReferences` that are attached to the request. This is a more advanced example that shows how you can use the [@vscode/prompt-tsx](https://www.npmjs.com/package/@vscode/prompt-tsx) library to implement the LLM tool calling flow and tries to implement all the features of the chat API.
|
||||
See [toolParticipant.ts](src/toolParticipant.ts) for an example of a chat participant that invokes tools, either dynamically or using the `toolReferences` that are attached to the request. This is a more advanced example that shows how you can use the [@vscode/prompt-tsx](https://www.npmjs.com/package/@vscode/prompt-tsx) library to implement the LLM tool calling flow and tries to implement all the features of the chat API.
|
||||
|
||||
25
chat-sample/package-lock.json
generated
25
chat-sample/package-lock.json
generated
@ -8,12 +8,14 @@
|
||||
"name": "chat-sample",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@vscode/chat-extension-utils": "^0.0.0-alpha.1",
|
||||
"@vscode/prompt-tsx": "^0.3.0-alpha.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.13.0",
|
||||
"@stylistic/eslint-plugin": "^2.9.0",
|
||||
"@types/node": "^20",
|
||||
"@types/vscode": "^1.95.0",
|
||||
"eslint": "^9.13.0",
|
||||
"typescript": "^5.6.2",
|
||||
"typescript-eslint": "^8.11.0"
|
||||
@ -278,6 +280,13 @@
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/vscode": {
|
||||
"version": "1.95.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.95.0.tgz",
|
||||
"integrity": "sha512-0LBD8TEiNbet3NvWsmn59zLzOFu/txSlGxnv5yAFHCrhG9WvAnR3IvfHzMOs2aeWqgvNjq9pO99IUw8d3n+unw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils": {
|
||||
"version": "8.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.11.0.tgz",
|
||||
@ -505,10 +514,20 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@vscode/chat-extension-utils": {
|
||||
"version": "0.0.0-alpha.1",
|
||||
"resolved": "https://registry.npmjs.org/@vscode/chat-extension-utils/-/chat-extension-utils-0.0.0-alpha.1.tgz",
|
||||
"integrity": "sha512-49eYur98d1iukPEQqMYQL4lJgaKnM0QFQB4/BFIFvuuKM+Kug2KNE/TSIJJQXrp5CrP0kDOmIIXvTnNRPtO2vg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vscode/prompt-tsx": "^0.3.0-alpha.13"
|
||||
}
|
||||
},
|
||||
"node_modules/@vscode/prompt-tsx": {
|
||||
"version": "0.3.0-alpha.12",
|
||||
"resolved": "https://registry.npmjs.org/@vscode/prompt-tsx/-/prompt-tsx-0.3.0-alpha.12.tgz",
|
||||
"integrity": "sha512-2ANm569UBXIzjPbaDFjzRkucelhsnlnmYIPdDo+USeFq2Do0Q70gKiiRWYrQf5rPqCxrChDvgU14nsdJLUSaOQ=="
|
||||
"version": "0.3.0-alpha.13",
|
||||
"resolved": "https://registry.npmjs.org/@vscode/prompt-tsx/-/prompt-tsx-0.3.0-alpha.13.tgz",
|
||||
"integrity": "sha512-0m9Hy2VqfGcFgXmY7xFV1nYngoq2zm2Wy/3YdesmR6bOwFrJed9xW87y43Ax7UFVHwtjZkpjn4M9HbFvxvzdWA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.13.0",
|
||||
|
||||
@ -72,6 +72,19 @@
|
||||
"description": "Use all registered tools. By default, only this extension's tools are used."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "chat-tools-sample.catTools",
|
||||
"fullName": "Cat (Tools)",
|
||||
"name": "catTools",
|
||||
"description": "I use tools, implemented using @vscode/chat-extension-utils, and am also a cat",
|
||||
"isSticky": true,
|
||||
"commands": [
|
||||
{
|
||||
"name": "all",
|
||||
"description": "Use all registered tools. By default, only this extension's tools are used."
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"languageModelTools": [
|
||||
@ -155,12 +168,14 @@
|
||||
"watch": "tsc -watch -p ./"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vscode/chat-extension-utils": "^0.0.0-alpha.1",
|
||||
"@vscode/prompt-tsx": "^0.3.0-alpha.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.13.0",
|
||||
"@stylistic/eslint-plugin": "^2.9.0",
|
||||
"@types/node": "^20",
|
||||
"@types/vscode": "^1.95.0",
|
||||
"eslint": "^9.13.0",
|
||||
"typescript": "^5.6.2",
|
||||
"typescript-eslint": "^8.11.0"
|
||||
|
||||
35
chat-sample/src/chatUtilsSample.ts
Normal file
35
chat-sample/src/chatUtilsSample.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import * as vscode from 'vscode';
|
||||
import * as chatUtils from '@vscode/chat-extension-utils';
|
||||
|
||||
export function registerChatLibChatParticipant(context: vscode.ExtensionContext) {
|
||||
const handler: vscode.ChatRequestHandler = async (request: vscode.ChatRequest, chatContext: vscode.ChatContext, stream: vscode.ChatResponseStream, token: vscode.CancellationToken) => {
|
||||
if (request.command === 'list') {
|
||||
stream.markdown(`Available tools: ${vscode.lm.tools.map(tool => tool.name).join(', ')}\n\n`);
|
||||
return;
|
||||
}
|
||||
|
||||
const tools = request.command === 'all' ?
|
||||
vscode.lm.tools :
|
||||
vscode.lm.tools.filter(tool => tool.tags.includes('chat-tools-sample'));
|
||||
|
||||
const libResult = chatUtils.sendChatParticipantRequest(
|
||||
request,
|
||||
chatContext,
|
||||
{
|
||||
prompt: 'You are a cat! Answer as a cat.',
|
||||
responseStreamOptions: {
|
||||
stream,
|
||||
references: true,
|
||||
responseText: true
|
||||
},
|
||||
tools
|
||||
},
|
||||
token);
|
||||
|
||||
return await libResult.result;
|
||||
};
|
||||
|
||||
const chatLibParticipant = vscode.chat.createChatParticipant('chat-tools-sample.catTools', handler);
|
||||
chatLibParticipant.iconPath = vscode.Uri.joinPath(context.extensionUri, 'cat.jpeg');
|
||||
context.subscriptions.push(chatLibParticipant);
|
||||
}
|
||||
@ -1,18 +1,15 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { FindFilesTool, RunInTerminalTool, TabCountTool } from './tools';
|
||||
import { registerToolUserChatParticipant } from './toolParticipant';
|
||||
import { registerChatLibChatParticipant } from './chatUtilsSample';
|
||||
import { registerSimpleParticipant } from './simple';
|
||||
import { registerToolUserChatParticipant } from './toolParticipant';
|
||||
import { registerChatTools } from './tools';
|
||||
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
registerSimpleParticipant(context);
|
||||
registerChatTools(context);
|
||||
registerToolUserChatParticipant(context);
|
||||
}
|
||||
registerChatLibChatParticipant(context);
|
||||
|
||||
function registerChatTools(context: vscode.ExtensionContext) {
|
||||
context.subscriptions.push(vscode.lm.registerTool('chat-tools-sample_tabCount', new TabCountTool()));
|
||||
context.subscriptions.push(vscode.lm.registerTool('chat-tools-sample_findFiles', new FindFilesTool()));
|
||||
context.subscriptions.push(vscode.lm.registerTool('chat-tools-sample_runInTerminal', new RunInTerminalTool()));
|
||||
registerChatTools(context);
|
||||
}
|
||||
|
||||
export function deactivate() { }
|
||||
|
||||
@ -13,7 +13,7 @@ interface ICatChatResult extends vscode.ChatResult {
|
||||
|
||||
export function registerSimpleParticipant(context: vscode.ExtensionContext) {
|
||||
|
||||
// Define a Cat chat handler.
|
||||
// Define a Cat chat handler.
|
||||
const handler: vscode.ChatRequestHandler = async (request: vscode.ChatRequest, context: vscode.ChatContext, stream: vscode.ChatResponseStream, token: vscode.CancellationToken): Promise<ICatChatResult> => {
|
||||
// To talk to an LLM in your subcommand handler implementation, your
|
||||
// extension can use VS Code's `requestChatAccess` API to access the Copilot API.
|
||||
|
||||
@ -1,5 +1,11 @@
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export function registerChatTools(context: vscode.ExtensionContext) {
|
||||
context.subscriptions.push(vscode.lm.registerTool('chat-tools-sample_tabCount', new TabCountTool()));
|
||||
context.subscriptions.push(vscode.lm.registerTool('chat-tools-sample_findFiles', new FindFilesTool()));
|
||||
context.subscriptions.push(vscode.lm.registerTool('chat-tools-sample_runInTerminal', new RunInTerminalTool()));
|
||||
}
|
||||
|
||||
interface ITabCountParameters {
|
||||
tabGroup?: number;
|
||||
}
|
||||
@ -7,7 +13,7 @@ interface ITabCountParameters {
|
||||
export class TabCountTool implements vscode.LanguageModelTool<ITabCountParameters> {
|
||||
async invoke(
|
||||
options: vscode.LanguageModelToolInvocationOptions<ITabCountParameters>,
|
||||
token: vscode.CancellationToken
|
||||
_token: vscode.CancellationToken
|
||||
) {
|
||||
const params = options.input;
|
||||
if (typeof params.tabGroup === 'number') {
|
||||
@ -16,10 +22,10 @@ export class TabCountTool implements vscode.LanguageModelTool<ITabCountParameter
|
||||
params.tabGroup === 1
|
||||
? '1st'
|
||||
: params.tabGroup === 2
|
||||
? '2nd'
|
||||
: params.tabGroup === 3
|
||||
? '3rd'
|
||||
: `${params.tabGroup}th`;
|
||||
? '2nd'
|
||||
: params.tabGroup === 3
|
||||
? '3rd'
|
||||
: `${params.tabGroup}th`;
|
||||
return new vscode.LanguageModelToolResult([new vscode.LanguageModelTextPart(`There are ${group.tabs.length} tabs open in the ${nth} tab group.`)]);
|
||||
} else {
|
||||
const group = vscode.window.tabGroups.activeTabGroup;
|
||||
@ -29,15 +35,15 @@ export class TabCountTool implements vscode.LanguageModelTool<ITabCountParameter
|
||||
|
||||
async prepareInvocation(
|
||||
options: vscode.LanguageModelToolInvocationPrepareOptions<ITabCountParameters>,
|
||||
token: vscode.CancellationToken
|
||||
_token: vscode.CancellationToken
|
||||
) {
|
||||
const confirmationMessages = {
|
||||
title: 'Count the number of open tabs',
|
||||
message: new vscode.MarkdownString(
|
||||
`Count the number of open tabs?` +
|
||||
(options.input.tabGroup !== undefined
|
||||
? ` in tab group ${options.input.tabGroup}`
|
||||
: '')
|
||||
(options.input.tabGroup !== undefined
|
||||
? ` in tab group ${options.input.tabGroup}`
|
||||
: '')
|
||||
),
|
||||
};
|
||||
|
||||
@ -71,7 +77,7 @@ export class FindFilesTool implements vscode.LanguageModelTool<IFindFilesParamet
|
||||
|
||||
async prepareInvocation(
|
||||
options: vscode.LanguageModelToolInvocationPrepareOptions<IFindFilesParameters>,
|
||||
token: vscode.CancellationToken
|
||||
_token: vscode.CancellationToken
|
||||
) {
|
||||
return {
|
||||
invocationMessage: `Searching workspace for "${options.input.pattern}"`,
|
||||
@ -89,7 +95,7 @@ async function waitForShellIntegration(
|
||||
): Promise<void> {
|
||||
let resolve: () => void;
|
||||
let reject: (e: Error) => void;
|
||||
let p = new Promise<void>((_resolve, _reject) => {
|
||||
const p = new Promise<void>((_resolve, _reject) => {
|
||||
resolve = _resolve;
|
||||
reject = _reject;
|
||||
});
|
||||
@ -108,11 +114,10 @@ async function waitForShellIntegration(
|
||||
}
|
||||
|
||||
export class RunInTerminalTool
|
||||
implements vscode.LanguageModelTool<IRunInTerminalParameters>
|
||||
{
|
||||
implements vscode.LanguageModelTool<IRunInTerminalParameters> {
|
||||
async invoke(
|
||||
options: vscode.LanguageModelToolInvocationOptions<IRunInTerminalParameters>,
|
||||
token: vscode.CancellationToken
|
||||
_token: vscode.CancellationToken
|
||||
) {
|
||||
const params = options.input as IRunInTerminalParameters;
|
||||
|
||||
@ -120,7 +125,7 @@ export class RunInTerminalTool
|
||||
terminal.show();
|
||||
try {
|
||||
await waitForShellIntegration(terminal, 5000);
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
return new vscode.LanguageModelToolResult([new vscode.LanguageModelTextPart((e as Error).message)]);
|
||||
}
|
||||
|
||||
@ -137,13 +142,13 @@ export class RunInTerminalTool
|
||||
|
||||
async prepareInvocation(
|
||||
options: vscode.LanguageModelToolInvocationPrepareOptions<IRunInTerminalParameters>,
|
||||
token: vscode.CancellationToken
|
||||
_token: vscode.CancellationToken
|
||||
) {
|
||||
const confirmationMessages = {
|
||||
title: 'Run command in terminal',
|
||||
message: new vscode.MarkdownString(
|
||||
`Run this command in a terminal?` +
|
||||
`\n\n\`\`\`\n${options.input.command}\n\`\`\`\n`
|
||||
`\n\n\`\`\`\n${options.input.command}\n\`\`\`\n`
|
||||
),
|
||||
};
|
||||
|
||||
|
||||
@ -57,7 +57,7 @@ export class ToolUserPrompt extends PromptElement<ToolUserProps, void> {
|
||||
<ToolCalls
|
||||
toolCallRounds={this.props.toolCallRounds}
|
||||
toolInvocationToken={this.props.request.toolInvocationToken}
|
||||
toolCallResults={this.props.toolCallResults}/>
|
||||
toolCallResults={this.props.toolCallResults} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
20074
chat-sample/vscode.d.ts
vendored
20074
chat-sample/vscode.d.ts
vendored
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user