Chat Agent Sample -> Chat Sample

fyi @roblourens
This commit is contained in:
isidor
2024-02-22 15:47:34 +01:00
parent b31d05bc9b
commit aee5500a8e
15 changed files with 1 additions and 1 deletions

View 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
View File

@ -0,0 +1,5 @@
out
dist
node_modules
.vscode-test/
*.vsix

35
chat-sample/.vscode/launch.json vendored Normal file
View 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
View 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
View 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
View 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.
![demo](./demo.png)
## 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

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

File diff suppressed because it is too large Load Diff

41
chat-sample/package.json Normal file
View 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"
}
}

View 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() { }

View 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;
}
}

View 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[]>;
}
}

View 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
View 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. */
}
}