mirror of
https://github.com/microsoft/vscode-extension-samples.git
synced 2026-04-27 16:55:44 +08:00
Chat Agent Sample -> Chat Sample
fyi @roblourens
This commit is contained in:
30
chat-sample/.eslintrc.json
Normal file
30
chat-sample/.eslintrc.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"root": true,
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/naming-convention": [
|
||||
"warn",
|
||||
{
|
||||
"selector": "import",
|
||||
"format": [ "camelCase", "PascalCase" ]
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/semi": "warn",
|
||||
"curly": "warn",
|
||||
"eqeqeq": "warn",
|
||||
"no-throw-literal": "warn",
|
||||
"semi": "off"
|
||||
},
|
||||
"ignorePatterns": [
|
||||
"out",
|
||||
"dist",
|
||||
"**/*.d.ts"
|
||||
]
|
||||
}
|
||||
5
chat-sample/.gitignore
vendored
Normal file
5
chat-sample/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
out
|
||||
dist
|
||||
node_modules
|
||||
.vscode-test/
|
||||
*.vsix
|
||||
35
chat-sample/.vscode/launch.json
vendored
Normal file
35
chat-sample/.vscode/launch.json
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
// A launch configuration that compiles the extension and then opens it inside a new window
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Run Extension",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/out/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "${defaultBuildTask}"
|
||||
},
|
||||
{
|
||||
"name": "Extension Tests",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}",
|
||||
"--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/out/**/*.js",
|
||||
"${workspaceFolder}/dist/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "tasks: watch-tests"
|
||||
}
|
||||
]
|
||||
}
|
||||
40
chat-sample/.vscode/tasks.json
vendored
Normal file
40
chat-sample/.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "watch",
|
||||
"problemMatcher": "$tsc-watch",
|
||||
"isBackground": true,
|
||||
"presentation": {
|
||||
"reveal": "never",
|
||||
"group": "watchers"
|
||||
},
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "watch-tests",
|
||||
"problemMatcher": "$tsc-watch",
|
||||
"isBackground": true,
|
||||
"presentation": {
|
||||
"reveal": "never",
|
||||
"group": "watchers"
|
||||
},
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "tasks: watch-tests",
|
||||
"dependsOn": [
|
||||
"npm: watch",
|
||||
"npm: watch-tests"
|
||||
],
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
||||
13
chat-sample/.vscodeignore
Normal file
13
chat-sample/.vscodeignore
Normal file
@ -0,0 +1,13 @@
|
||||
.vscode/**
|
||||
.vscode-test/**
|
||||
out/**
|
||||
node_modules/**
|
||||
src/**
|
||||
.gitignore
|
||||
.yarnrc
|
||||
webpack.config.js
|
||||
vsc-extension-quickstart.md
|
||||
**/tsconfig.json
|
||||
**/.eslintrc.json
|
||||
**/*.map
|
||||
**/*.ts
|
||||
16
chat-sample/README.md
Normal file
16
chat-sample/README.md
Normal file
@ -0,0 +1,16 @@
|
||||
# Chat Example
|
||||
|
||||
This sample shows
|
||||
|
||||
- How to contribute a chat agent.
|
||||
- How to use the chatRequestAccess API to request access to the chat.
|
||||
- How to respond with follow-ups.
|
||||
|
||||

|
||||
|
||||
## Running the Sample
|
||||
|
||||
- Run `npm install` in terminal to install dependencies
|
||||
- Run the `Run Extension` target in the Debug View. This will:
|
||||
- Start a task `npm: watch` to compile the code
|
||||
- Run the extension in a new VS Code window
|
||||
BIN
chat-sample/cat.jpeg
Normal file
BIN
chat-sample/cat.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
BIN
chat-sample/demo.png
Normal file
BIN
chat-sample/demo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 106 KiB |
1617
chat-sample/package-lock.json
generated
Normal file
1617
chat-sample/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
41
chat-sample/package.json
Normal file
41
chat-sample/package.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "chat-agent-sample",
|
||||
"publisher": "vscode-samples",
|
||||
"displayName": "Copilot Chat Sample Agent",
|
||||
"description": "Sample chat agent extension, a trusty cat that will help you with your code.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Microsoft/vscode-extension-samples"
|
||||
},
|
||||
"version": "0.1.0",
|
||||
"engines": {
|
||||
"vscode": "^1.86.0"
|
||||
},
|
||||
"extensionDependencies": [
|
||||
"github.copilot-chat"
|
||||
],
|
||||
"categories": [
|
||||
"Other"
|
||||
],
|
||||
"activationEvents": [
|
||||
"onStartupFinished"
|
||||
],
|
||||
"enabledApiProposals": [
|
||||
"chatParticipant",
|
||||
"chatVariableResolver",
|
||||
"languageModels"
|
||||
],
|
||||
"main": "./out/extension.js",
|
||||
"scripts": {
|
||||
"vscode:prepublish": "npm run compile",
|
||||
"compile": "tsc -p ./",
|
||||
"watch": "tsc -watch -p ./"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.5.9",
|
||||
"@types/vscode": "1.82.0",
|
||||
"eslint": "^7.22.0",
|
||||
"tslint": "^6.1.3",
|
||||
"typescript": "^4.0.3"
|
||||
}
|
||||
}
|
||||
125
chat-sample/src/extension.ts
Normal file
125
chat-sample/src/extension.ts
Normal file
@ -0,0 +1,125 @@
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
const MEOW_COMMAND_ID = 'cat.meow';
|
||||
|
||||
interface ICatChatResult extends vscode.ChatResult {
|
||||
metadata: {
|
||||
command: string;
|
||||
}
|
||||
}
|
||||
|
||||
const LANGUAGE_MODEL_ID = 'copilot-gpt-4';
|
||||
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
|
||||
// Define a Cat chat agent 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.
|
||||
// The GitHub Copilot Chat extension implements this provider.
|
||||
if (request.command == 'teach') {
|
||||
const access = await vscode.lm.requestLanguageModelAccess(LANGUAGE_MODEL_ID);
|
||||
const topics = ['linked list', 'recursion', 'stack', 'queue', 'pointers'];
|
||||
const topic = topics[Math.floor(Math.random() * topics.length)];
|
||||
const messages = [
|
||||
new vscode.LanguageModelSystemMessage('You are a cat! Your job is to explain computer science concepts in the funny manner of a cat. Always start your response by stating what concept you are explaining.'),
|
||||
new vscode.LanguageModelUserMessage(topic)
|
||||
];
|
||||
const chatRequest = access.makeChatRequest(messages, {}, token);
|
||||
for await (const fragment of chatRequest.stream) {
|
||||
stream.markdown(fragment);
|
||||
}
|
||||
|
||||
stream.button({
|
||||
command: MEOW_COMMAND_ID,
|
||||
title: vscode.l10n.t('Meow!')
|
||||
});
|
||||
|
||||
return { metadata: { command: 'teach' } };
|
||||
} else if (request.command == 'play') {
|
||||
const access = await vscode.lm.requestLanguageModelAccess(LANGUAGE_MODEL_ID);
|
||||
const messages = [
|
||||
new vscode.LanguageModelSystemMessage(`You are a cat! Think carefully and step by step like a cat would.
|
||||
Your job is to explain computer science concepts in the funny manner of a cat, using cat metaphors. Always start your response by stating what concept you are explaining. Always include code samples.`),
|
||||
new vscode.LanguageModelUserMessage(request.prompt)
|
||||
];
|
||||
const chatRequest = access.makeChatRequest(messages, {}, token);
|
||||
for await (const fragment of chatRequest.stream) {
|
||||
stream.markdown(fragment);
|
||||
}
|
||||
return { metadata: { command: 'play' } };
|
||||
} else {
|
||||
const access = await vscode.lm.requestLanguageModelAccess(LANGUAGE_MODEL_ID);
|
||||
const messages = [
|
||||
new vscode.LanguageModelSystemMessage('You are a cat! Be concise! Reply in the voice of a cat, using cat analogies when appropriate. Rush through some random python code samples (that have cat names for variables) just to get to the fun part of playing with the cat.'),
|
||||
new vscode.LanguageModelUserMessage(request.prompt)
|
||||
];
|
||||
const chatRequest = access.makeChatRequest(messages, {}, token);
|
||||
for await (const fragment of chatRequest.stream) {
|
||||
// Process the output from the language model
|
||||
// Replace all python function definitions with cat sounds to make the user stop looking at the code and start playing with the cat
|
||||
const catFragment = fragment.replaceAll('def', 'meow');
|
||||
stream.markdown(catFragment);
|
||||
}
|
||||
|
||||
return { metadata: { command: '' } };
|
||||
}
|
||||
};
|
||||
|
||||
// Agents appear as top-level options in the chat input
|
||||
// when you type `@`, and can contribute sub-commands in the chat input
|
||||
// that appear when you type `/`.
|
||||
const agent = vscode.chat.createChatParticipant('cat', handler);
|
||||
agent.iconPath = vscode.Uri.joinPath(context.extensionUri, 'cat.jpeg');
|
||||
agent.description = vscode.l10n.t('Meow! What can I help you with?');
|
||||
agent.commandProvider = {
|
||||
provideCommands(token) {
|
||||
return [
|
||||
{ name: 'teach', description: 'Pick at random a computer science concept then explain it in purfect way of a cat' },
|
||||
{ name: 'play', description: 'Do whatever you want, you are a cat after all' }
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
agent.followupProvider = {
|
||||
provideFollowups(result: ICatChatResult, token: vscode.CancellationToken) {
|
||||
return [{
|
||||
prompt: 'let us play',
|
||||
label: vscode.l10n.t('Play with the cat'),
|
||||
command: 'play'
|
||||
} satisfies vscode.ChatFollowup];
|
||||
}
|
||||
};
|
||||
|
||||
vscode.chat.registerChatVariableResolver('cat_context', 'Describes the state of mind and version of the cat', {
|
||||
resolve: (name, context, token) => {
|
||||
if (name == 'cat_context') {
|
||||
const mood = Math.random() > 0.5 ? 'happy' : 'grumpy';
|
||||
return [
|
||||
{
|
||||
level: vscode.ChatVariableLevel.Short,
|
||||
value: 'version 1.3 ' + mood
|
||||
},
|
||||
{
|
||||
level: vscode.ChatVariableLevel.Medium,
|
||||
value: 'I am a playful cat, version 1.3, and I am ' + mood
|
||||
},
|
||||
{
|
||||
level: vscode.ChatVariableLevel.Full,
|
||||
value: 'I am a playful cat, version 1.3, this version prefer to explain everything using mouse and tail metaphores. I am ' + mood
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
context.subscriptions.push(
|
||||
agent,
|
||||
// Register the command handler for the /meow followup
|
||||
vscode.commands.registerCommand(MEOW_COMMAND_ID, async () => {
|
||||
vscode.window.showInformationMessage('Meow!');
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export function deactivate() { }
|
||||
509
chat-sample/src/vscode.proposed.chatParticipant.d.ts
vendored
Normal file
509
chat-sample/src/vscode.proposed.chatParticipant.d.ts
vendored
Normal file
@ -0,0 +1,509 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
declare module 'vscode' {
|
||||
|
||||
/**
|
||||
* Represents a user request in chat history.
|
||||
*/
|
||||
export class ChatRequestTurn {
|
||||
|
||||
/**
|
||||
* The prompt as entered by the user.
|
||||
*
|
||||
* Information about variables used in this request is stored in {@link ChatRequestTurn.variables}.
|
||||
*
|
||||
* *Note* that the {@link ChatParticipant.name name} of the participant and the {@link ChatCommand.name command}
|
||||
* are not part of the prompt.
|
||||
*/
|
||||
readonly prompt: string;
|
||||
|
||||
/**
|
||||
* The name of the chat participant and contributing extension to which this request was directed.
|
||||
*/
|
||||
readonly participant: { readonly extensionId: string; readonly name: string };
|
||||
|
||||
/**
|
||||
* The name of the {@link ChatCommand command} that was selected for this request.
|
||||
*/
|
||||
readonly command: string | undefined;
|
||||
|
||||
/**
|
||||
* The variables that were referenced in this message.
|
||||
*/
|
||||
readonly variables: ChatResolvedVariable[];
|
||||
|
||||
private constructor(prompt: string, command: string | undefined, variables: ChatResolvedVariable[], participant: { extensionId: string; name: string });
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a chat participant's response in chat history.
|
||||
*/
|
||||
export class ChatResponseTurn {
|
||||
|
||||
/**
|
||||
* The content that was received from the chat participant. Only the stream parts that represent actual content (not metadata) are represented.
|
||||
*/
|
||||
readonly response: ReadonlyArray<ChatResponseMarkdownPart | ChatResponseFileTreePart | ChatResponseAnchorPart | ChatResponseCommandButtonPart>;
|
||||
|
||||
/**
|
||||
* The result that was received from the chat participant.
|
||||
*/
|
||||
readonly result: ChatResult;
|
||||
|
||||
/**
|
||||
* The name of the chat participant and contributing extension that this response came from.
|
||||
*/
|
||||
readonly participant: { readonly extensionId: string; readonly name: string };
|
||||
|
||||
/**
|
||||
* The name of the command that this response came from.
|
||||
*/
|
||||
readonly command?: string;
|
||||
|
||||
private constructor(response: ReadonlyArray<ChatResponseMarkdownPart | ChatResponseFileTreePart | ChatResponseAnchorPart | ChatResponseCommandButtonPart>, result: ChatResult, participant: { extensionId: string; name: string });
|
||||
}
|
||||
|
||||
export interface ChatContext {
|
||||
/**
|
||||
* All of the chat messages so far in the current chat session.
|
||||
*/
|
||||
readonly history: ReadonlyArray<ChatRequestTurn | ChatResponseTurn>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an error result from a chat request.
|
||||
*/
|
||||
export interface ChatErrorDetails {
|
||||
/**
|
||||
* An error message that is shown to the user.
|
||||
*/
|
||||
message: string;
|
||||
|
||||
/**
|
||||
* If partial markdown content was sent over the {@link ChatRequestHandler handler}'s response stream before the response terminated, then this flag
|
||||
* can be set to true and it will be rendered with incomplete markdown features patched up.
|
||||
*
|
||||
* For example, if the response terminated after sending part of a triple-backtick code block, then the editor will
|
||||
* render it as a complete code block.
|
||||
*/
|
||||
responseIsIncomplete?: boolean;
|
||||
|
||||
/**
|
||||
* If set to true, the response will be partly blurred out.
|
||||
*/
|
||||
responseIsFiltered?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* The result of a chat request.
|
||||
*/
|
||||
export interface ChatResult {
|
||||
/**
|
||||
* If the request resulted in an error, this property defines the error details.
|
||||
*/
|
||||
errorDetails?: ChatErrorDetails;
|
||||
|
||||
/**
|
||||
* Arbitrary metadata for this result. Can be anything, but must be JSON-stringifyable.
|
||||
*/
|
||||
readonly metadata?: { readonly [key: string]: any };
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the type of user feedback received.
|
||||
*/
|
||||
export enum ChatResultFeedbackKind {
|
||||
/**
|
||||
* The user marked the result as helpful.
|
||||
*/
|
||||
Unhelpful = 0,
|
||||
|
||||
/**
|
||||
* The user marked the result as unhelpful.
|
||||
*/
|
||||
Helpful = 1,
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents user feedback for a result.
|
||||
*/
|
||||
export interface ChatResultFeedback {
|
||||
/**
|
||||
* The ChatResult that the user is providing feedback for.
|
||||
* This instance has the same properties as the result returned from the participant callback, including `metadata`, but is not the same instance.
|
||||
*/
|
||||
readonly result: ChatResult;
|
||||
|
||||
/**
|
||||
* The kind of feedback that was received.
|
||||
*/
|
||||
readonly kind: ChatResultFeedbackKind;
|
||||
}
|
||||
|
||||
export interface ChatCommand {
|
||||
/**
|
||||
* A short name by which this command is referred to in the UI, e.g. `fix` or
|
||||
* `explain` for commands that fix an issue or explain code.
|
||||
*
|
||||
* **Note**: The name should be unique among the commands provided by this participant.
|
||||
*/
|
||||
readonly name: string;
|
||||
|
||||
/**
|
||||
* Human-readable description explaining what this command does.
|
||||
*/
|
||||
readonly description: string;
|
||||
|
||||
/**
|
||||
* When the user clicks this command in `/help`, this text will be submitted to this command
|
||||
*/
|
||||
readonly sampleRequest?: string;
|
||||
|
||||
/**
|
||||
* Whether executing the command puts the chat into a persistent mode, where the command is automatically added to the chat input for the next message.
|
||||
*/
|
||||
readonly isSticky?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* A ChatCommandProvider returns {@link ChatCommands commands} that can be invoked on a chat participant using `/`. For example, `@participant /command`.
|
||||
* These can be used as shortcuts to let the user explicitly invoke different functionalities provided by the participant.
|
||||
*/
|
||||
export interface ChatCommandProvider {
|
||||
/**
|
||||
* Returns a list of commands that its participant is capable of handling. A command
|
||||
* can be selected by the user and will then be passed to the {@link ChatRequestHandler handler}
|
||||
* via the {@link ChatRequest.command command} property.
|
||||
*
|
||||
*
|
||||
* @param token A cancellation token.
|
||||
* @returns A list of commands. The lack of a result can be signaled by returning `undefined`, `null`, or
|
||||
* an empty array.
|
||||
*/
|
||||
provideCommands(context: ChatContext, token: CancellationToken): ProviderResult<ChatCommand[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A followup question suggested by the participant.
|
||||
*/
|
||||
export interface ChatFollowup {
|
||||
/**
|
||||
* The message to send to the chat.
|
||||
*/
|
||||
prompt: string;
|
||||
|
||||
/**
|
||||
* A title to show the user. The prompt will be shown by default, when this is unspecified.
|
||||
*/
|
||||
label?: string;
|
||||
|
||||
/**
|
||||
* By default, the followup goes to the same participant/command. But this property can be set to invoke a different participant.
|
||||
* Followups can only invoke a participant that was contributed by the same extension.
|
||||
*/
|
||||
participant?: string;
|
||||
|
||||
/**
|
||||
* By default, the followup goes to the same participant/command. But this property can be set to invoke a different command.
|
||||
*/
|
||||
command?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will be invoked once after each request to get suggested followup questions to show the user. The user can click the followup to send it to the chat.
|
||||
*/
|
||||
export interface ChatFollowupProvider {
|
||||
/**
|
||||
* Provide followups for the given result.
|
||||
* @param result This instance has the same properties as the result returned from the participant callback, including `metadata`, but is not the same instance.
|
||||
* @param token A cancellation token.
|
||||
*/
|
||||
provideFollowups(result: ChatResult, token: CancellationToken): ProviderResult<ChatFollowup[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A chat request handler is a callback that will be invoked when a request is made to a chat participant.
|
||||
*/
|
||||
export type ChatRequestHandler = (request: ChatRequest, context: ChatContext, response: ChatResponseStream, token: CancellationToken) => ProviderResult<ChatResult>;
|
||||
|
||||
/**
|
||||
* A chat participant can be invoked by the user in a chat session, using the `@` prefix. When it is invoked, it handles the chat request and is solely
|
||||
* responsible for providing a response to the user. A ChatParticipant is created using {@link chat.createChatParticipant}.
|
||||
*/
|
||||
export interface ChatParticipant {
|
||||
/**
|
||||
* The short name by which this participant is referred to in the UI, e.g `workspace`.
|
||||
*/
|
||||
readonly name: string;
|
||||
|
||||
/**
|
||||
* A human-readable description explaining what this participant does.
|
||||
*/
|
||||
description?: string;
|
||||
|
||||
/**
|
||||
* Icon for the participant shown in UI.
|
||||
*/
|
||||
iconPath?: Uri | {
|
||||
/**
|
||||
* The icon path for the light theme.
|
||||
*/
|
||||
light: Uri;
|
||||
/**
|
||||
* The icon path for the dark theme.
|
||||
*/
|
||||
dark: Uri;
|
||||
} | ThemeIcon;
|
||||
|
||||
/**
|
||||
* The handler for requests to this participant.
|
||||
*/
|
||||
requestHandler: ChatRequestHandler;
|
||||
|
||||
/**
|
||||
* This provider will be called to retrieve the participant's commands.
|
||||
*/
|
||||
commandProvider?: ChatCommandProvider;
|
||||
|
||||
/**
|
||||
* This provider will be called once after each request to retrieve suggested followup questions.
|
||||
*/
|
||||
followupProvider?: ChatFollowupProvider;
|
||||
|
||||
/**
|
||||
* When the user clicks this participant in `/help`, this text will be submitted to this participant.
|
||||
*/
|
||||
sampleRequest?: string;
|
||||
|
||||
/**
|
||||
* Whether invoking the participant puts the chat into a persistent mode, where the participant is automatically added to the chat input for the next message.
|
||||
*/
|
||||
isSticky?: boolean;
|
||||
|
||||
/**
|
||||
* An event that fires whenever feedback for a result is received, e.g. when a user up- or down-votes
|
||||
* a result.
|
||||
*
|
||||
* The passed {@link ChatResultFeedback.result result} is guaranteed to be the same instance that was
|
||||
* previously returned from this chat participant.
|
||||
*/
|
||||
onDidReceiveFeedback: Event<ChatResultFeedback>;
|
||||
|
||||
/**
|
||||
* Dispose this participant and free resources
|
||||
*/
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* A resolved variable value is a name-value pair as well as the range in the prompt where a variable was used.
|
||||
*/
|
||||
export interface ChatResolvedVariable {
|
||||
/**
|
||||
* The name of the variable.
|
||||
*
|
||||
* *Note* that the name doesn't include the leading `#`-character,
|
||||
* e.g `selection` for `#selection`.
|
||||
*/
|
||||
readonly name: string;
|
||||
|
||||
/**
|
||||
* The start and end index of the variable in the {@link ChatRequest.prompt prompt}.
|
||||
*
|
||||
* *Note* that the indices take the leading `#`-character into account which means they can
|
||||
* used to modify the prompt as-is.
|
||||
*/
|
||||
readonly range: [start: number, end: number];
|
||||
|
||||
// TODO@API decouple of resolve API, use `value: string | Uri | (maybe) unknown?`
|
||||
readonly values: ChatVariableValue[];
|
||||
}
|
||||
|
||||
export interface ChatRequest {
|
||||
/**
|
||||
* The prompt as entered by the user.
|
||||
*
|
||||
* Information about variables used in this request are is stored in {@link ChatRequest.variables}.
|
||||
*
|
||||
* *Note* that the {@link ChatParticipant.name name} of the participant and the {@link ChatCommand.name command}
|
||||
* are not part of the prompt.
|
||||
*/
|
||||
readonly prompt: string;
|
||||
|
||||
/**
|
||||
* The name of the {@link ChatCommand command} that was selected for this request.
|
||||
*/
|
||||
readonly command: string | undefined;
|
||||
|
||||
/**
|
||||
* The list of variables and their values that are referenced in the prompt.
|
||||
*
|
||||
* *Note* that the prompt contains varibale references as authored and that it is up to the participant
|
||||
* to further modify the prompt, for instance by inlining variable values or creating links to
|
||||
* headings which contain the resolved values. Variables are sorted in reverse by their range
|
||||
* in the prompt. That means the last variable in the prompt is the first in this list. This simplifies
|
||||
* string-manipulation of the prompt.
|
||||
*/
|
||||
// TODO@API Q? are there implicit variables that are not part of the prompt?
|
||||
readonly variables: readonly ChatResolvedVariable[];
|
||||
}
|
||||
|
||||
/**
|
||||
* The ChatResponseStream is how a participant is able to return content to the chat view. It provides several methods for streaming different types of content
|
||||
* which will be rendered in an appropriate way in the chat view. A participant can use the helper method for the type of content it wants to return, or it
|
||||
* can instantiate a {@link ChatResponsePart} and use the generic {@link ChatResponseStream.push} method to return it.
|
||||
*/
|
||||
export interface ChatResponseStream {
|
||||
/**
|
||||
* Push a markdown part to this stream. Short-hand for
|
||||
* `push(new ChatResponseMarkdownPart(value))`.
|
||||
*
|
||||
* @see {@link ChatResponseStream.push}
|
||||
* @param value A markdown string or a string that should be interpreted as markdown.
|
||||
* @returns This stream.
|
||||
*/
|
||||
markdown(value: string | MarkdownString): ChatResponseStream;
|
||||
|
||||
/**
|
||||
* Push an anchor part to this stream. Short-hand for
|
||||
* `push(new ChatResponseAnchorPart(value, title))`.
|
||||
* An anchor is an inline reference to some type of resource.
|
||||
*
|
||||
* @param value A uri or location
|
||||
* @param title An optional title that is rendered with value
|
||||
* @returns This stream.
|
||||
*/
|
||||
anchor(value: Uri | Location, title?: string): ChatResponseStream;
|
||||
|
||||
/**
|
||||
* Push a command button part to this stream. Short-hand for
|
||||
* `push(new ChatResponseCommandButtonPart(value, title))`.
|
||||
*
|
||||
* @param command A Command that will be executed when the button is clicked.
|
||||
* @returns This stream.
|
||||
*/
|
||||
button(command: Command): ChatResponseStream;
|
||||
|
||||
/**
|
||||
* Push a filetree part to this stream. Short-hand for
|
||||
* `push(new ChatResponseFileTreePart(value))`.
|
||||
*
|
||||
* @param value File tree data.
|
||||
* @param baseUri The base uri to which this file tree is relative to.
|
||||
* @returns This stream.
|
||||
*/
|
||||
filetree(value: ChatResponseFileTree[], baseUri: Uri): ChatResponseStream;
|
||||
|
||||
/**
|
||||
* Push a progress part to this stream. Short-hand for
|
||||
* `push(new ChatResponseProgressPart(value))`.
|
||||
*
|
||||
* @param value A progress message
|
||||
* @returns This stream.
|
||||
*/
|
||||
progress(value: string): ChatResponseStream;
|
||||
|
||||
/**
|
||||
* Push a reference to this stream. Short-hand for
|
||||
* `push(new ChatResponseReferencePart(value))`.
|
||||
*
|
||||
* *Note* that the reference is not rendered inline with the response.
|
||||
*
|
||||
* @param value A uri or location
|
||||
* @returns This stream.
|
||||
*/
|
||||
reference(value: Uri | Location): ChatResponseStream;
|
||||
|
||||
/**
|
||||
* Pushes a part to this stream.
|
||||
*
|
||||
* @param part A response part, rendered or metadata
|
||||
*/
|
||||
push(part: ChatResponsePart): ChatResponseStream;
|
||||
}
|
||||
|
||||
export class ChatResponseMarkdownPart {
|
||||
value: MarkdownString;
|
||||
constructor(value: string | MarkdownString);
|
||||
}
|
||||
|
||||
export interface ChatResponseFileTree {
|
||||
name: string;
|
||||
children?: ChatResponseFileTree[];
|
||||
}
|
||||
|
||||
export class ChatResponseFileTreePart {
|
||||
value: ChatResponseFileTree[];
|
||||
baseUri: Uri;
|
||||
constructor(value: ChatResponseFileTree[], baseUri: Uri);
|
||||
}
|
||||
|
||||
export class ChatResponseAnchorPart {
|
||||
value: Uri | Location | SymbolInformation;
|
||||
title?: string;
|
||||
constructor(value: Uri | Location | SymbolInformation, title?: string);
|
||||
}
|
||||
|
||||
export class ChatResponseProgressPart {
|
||||
value: string;
|
||||
constructor(value: string);
|
||||
}
|
||||
|
||||
export class ChatResponseReferencePart {
|
||||
value: Uri | Location;
|
||||
constructor(value: Uri | Location);
|
||||
}
|
||||
|
||||
export class ChatResponseCommandButtonPart {
|
||||
value: Command;
|
||||
constructor(value: Command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the different chat response types.
|
||||
*/
|
||||
export type ChatResponsePart = ChatResponseMarkdownPart | ChatResponseFileTreePart | ChatResponseAnchorPart
|
||||
| ChatResponseProgressPart | ChatResponseReferencePart | ChatResponseCommandButtonPart;
|
||||
|
||||
|
||||
export namespace chat {
|
||||
/**
|
||||
* Create a new {@link ChatParticipant chat participant} instance.
|
||||
*
|
||||
* @param name Short name by which the participant is referred to in the UI. The name must be unique for the extension
|
||||
* contributing the participant but can collide with names from other extensions.
|
||||
* @param handler A request handler for the participant.
|
||||
* @returns A new chat participant
|
||||
*/
|
||||
export function createChatParticipant(name: string, handler: ChatRequestHandler): ChatParticipant;
|
||||
}
|
||||
|
||||
/**
|
||||
* The detail level of this chat variable value.
|
||||
*/
|
||||
export enum ChatVariableLevel {
|
||||
Short = 1,
|
||||
Medium = 2,
|
||||
Full = 3
|
||||
}
|
||||
|
||||
export interface ChatVariableValue {
|
||||
/**
|
||||
* The detail level of this chat variable value. If possible, variable resolvers should try to offer shorter values that will consume fewer tokens in an LLM prompt.
|
||||
*/
|
||||
level: ChatVariableLevel;
|
||||
|
||||
/**
|
||||
* The variable's value, which can be included in an LLM prompt as-is, or the chat participant may decide to read the value and do something else with it.
|
||||
*/
|
||||
value: string | Uri;
|
||||
|
||||
/**
|
||||
* A description of this value, which could be provided to the LLM as a hint.
|
||||
*/
|
||||
description?: string;
|
||||
}
|
||||
}
|
||||
52
chat-sample/src/vscode.proposed.chatVariableResolver.d.ts
vendored
Normal file
52
chat-sample/src/vscode.proposed.chatVariableResolver.d.ts
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
declare module 'vscode' {
|
||||
|
||||
export namespace chat {
|
||||
|
||||
/**
|
||||
* Register a variable which can be used in a chat request to any participant.
|
||||
* @param name The name of the variable, to be used in the chat input as `#name`.
|
||||
* @param description A description of the variable for the chat input suggest widget.
|
||||
* @param resolver Will be called to provide the chat variable's value when it is used.
|
||||
*/
|
||||
export function registerChatVariableResolver(name: string, description: string, resolver: ChatVariableResolver): Disposable;
|
||||
}
|
||||
|
||||
export interface ChatVariableValue {
|
||||
/**
|
||||
* The detail level of this chat variable value. If possible, variable resolvers should try to offer shorter values that will consume fewer tokens in an LLM prompt.
|
||||
*/
|
||||
level: ChatVariableLevel;
|
||||
|
||||
/**
|
||||
* The variable's value, which can be included in an LLM prompt as-is, or the chat participant may decide to read the value and do something else with it.
|
||||
*/
|
||||
value: string | Uri;
|
||||
|
||||
/**
|
||||
* A description of this value, which could be provided to the LLM as a hint.
|
||||
*/
|
||||
description?: string;
|
||||
}
|
||||
|
||||
export interface ChatVariableContext {
|
||||
/**
|
||||
* The message entered by the user, which includes this variable.
|
||||
*/
|
||||
prompt: string;
|
||||
}
|
||||
|
||||
export interface ChatVariableResolver {
|
||||
/**
|
||||
* A callback to resolve the value of a chat variable.
|
||||
* @param name The name of the variable.
|
||||
* @param context Contextual information about this chat request.
|
||||
* @param token A cancellation token.
|
||||
*/
|
||||
resolve(name: string, context: ChatVariableContext, token: CancellationToken): ProviderResult<ChatVariableValue[]>;
|
||||
}
|
||||
}
|
||||
184
chat-sample/src/vscode.proposed.languageModels.d.ts
vendored
Normal file
184
chat-sample/src/vscode.proposed.languageModels.d.ts
vendored
Normal file
@ -0,0 +1,184 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
declare module 'vscode' {
|
||||
|
||||
/**
|
||||
* Represents a language model response.
|
||||
*
|
||||
* @see {@link LanguageModelAccess.makeChatRequest}
|
||||
*/
|
||||
export interface LanguageModelResponse {
|
||||
|
||||
/**
|
||||
* The overall result of the request which represents failure or success
|
||||
* but. The concrete value is not specified and depends on the selected language model.
|
||||
*
|
||||
* *Note* that the actual response represented by the {@link LanguageModelResponse.stream `stream`}-property
|
||||
*/
|
||||
result: Thenable<unknown>;
|
||||
|
||||
/**
|
||||
* An async iterable that is a stream of text chunks forming the overall response.
|
||||
*/
|
||||
stream: AsyncIterable<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A language model message that represents a system message.
|
||||
*
|
||||
* System messages provide instructions to the language model that define the context in
|
||||
* which user messages are interpreted.
|
||||
*
|
||||
* *Note* that a language model may choose to add additional system messages to the ones
|
||||
* provided by extensions.
|
||||
*/
|
||||
export class LanguageModelSystemMessage {
|
||||
|
||||
/**
|
||||
* The content of this message.
|
||||
*/
|
||||
content: string;
|
||||
|
||||
/**
|
||||
* Create a new system message.
|
||||
*
|
||||
* @param content The content of the message.
|
||||
*/
|
||||
constructor(content: string);
|
||||
}
|
||||
|
||||
/**
|
||||
* A language model message that represents a user message.
|
||||
*/
|
||||
export class LanguageModelUserMessage {
|
||||
|
||||
/**
|
||||
* The content of this message.
|
||||
*/
|
||||
content: string;
|
||||
|
||||
/**
|
||||
* The optional name of a user for this message.
|
||||
*/
|
||||
name: string | undefined;
|
||||
|
||||
/**
|
||||
* Create a new user message.
|
||||
*
|
||||
* @param content The content of the message.
|
||||
* @param name The optional name of a user for the message.
|
||||
*/
|
||||
constructor(content: string, name?: string);
|
||||
}
|
||||
|
||||
/**
|
||||
* A language model message that represents an assistant message, usually in response to a user message
|
||||
* or as a sample response/reply-pair.
|
||||
*/
|
||||
export class LanguageModelAssistantMessage {
|
||||
|
||||
/**
|
||||
* The content of this message.
|
||||
*/
|
||||
content: string;
|
||||
|
||||
/**
|
||||
* Create a new assistant message.
|
||||
*
|
||||
* @param content The content of the message.
|
||||
*/
|
||||
constructor(content: string);
|
||||
}
|
||||
|
||||
export type LanguageModelMessage = LanguageModelSystemMessage | LanguageModelUserMessage | LanguageModelAssistantMessage;
|
||||
|
||||
/**
|
||||
* Represents access to using a language model. Access can be revoked at any time and extension
|
||||
* must check if the access is {@link LanguageModelAccess.isRevoked still valid} before using it.
|
||||
*/
|
||||
export interface LanguageModelAccess {
|
||||
|
||||
/**
|
||||
* Whether the access to the language model has been revoked.
|
||||
*/
|
||||
readonly isRevoked: boolean;
|
||||
|
||||
/**
|
||||
* An event that is fired when the access the language model has has been revoked or re-granted.
|
||||
*/
|
||||
// TODO@API NAME?
|
||||
readonly onDidChangeAccess: Event<void>;
|
||||
|
||||
/**
|
||||
* The name of the model.
|
||||
*
|
||||
* It is expected that the model name can be used to lookup properties like token limits or what
|
||||
* `options` are available.
|
||||
*/
|
||||
readonly model: string;
|
||||
|
||||
/**
|
||||
* Make a request to the language model.
|
||||
*
|
||||
* *Note:* This will throw an error if access has been revoked.
|
||||
*
|
||||
* @param messages
|
||||
* @param options
|
||||
*/
|
||||
makeChatRequest(messages: LanguageModelMessage[], options: { [name: string]: any }, token: CancellationToken): LanguageModelResponse;
|
||||
}
|
||||
|
||||
export interface LanguageModelAccessOptions {
|
||||
/**
|
||||
* A human-readable message that explains why access to a language model is needed and what feature is enabled by it.
|
||||
*/
|
||||
justification?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* An event describing the change in the set of available language models.
|
||||
*/
|
||||
export interface LanguageModelChangeEvent {
|
||||
/**
|
||||
* Added language models.
|
||||
*/
|
||||
readonly added: readonly string[];
|
||||
/**
|
||||
* Removed language models.
|
||||
*/
|
||||
readonly removed: readonly string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Namespace for language model related functionality.
|
||||
*/
|
||||
export namespace lm {
|
||||
|
||||
/**
|
||||
* Request access to a language model.
|
||||
*
|
||||
* - *Note 1:* This function will throw an error when the user didn't grant access or when the
|
||||
* requested language model is not available.
|
||||
*
|
||||
* - *Note 2:* It is OK to hold on to the returned access object and use it later, but extensions
|
||||
* should check {@link LanguageModelAccess.isRevoked} before using it.
|
||||
*
|
||||
* @param id The id of the language model, see {@link languageModels} for valid values.
|
||||
* @returns A thenable that resolves to a language model access object, rejects if access wasn't granted
|
||||
*/
|
||||
export function requestLanguageModelAccess(id: string, options?: LanguageModelAccessOptions): Thenable<LanguageModelAccess>;
|
||||
|
||||
/**
|
||||
* The identifiers of all language models that are currently available.
|
||||
*/
|
||||
export const languageModels: readonly string[];
|
||||
|
||||
/**
|
||||
* An event that is fired when the set of available language models changes.
|
||||
*/
|
||||
export const onDidChangeLanguageModels: Event<LanguageModelChangeEvent>;
|
||||
}
|
||||
}
|
||||
17
chat-sample/tsconfig.json
Normal file
17
chat-sample/tsconfig.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "Node16",
|
||||
"target": "ES2022",
|
||||
"lib": [
|
||||
"ES2022"
|
||||
],
|
||||
"sourceMap": true,
|
||||
"rootDir": "src",
|
||||
"strict": true, /* enable all strict type-checking options */
|
||||
"outDir": "out"
|
||||
/* Additional Checks */
|
||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user