2023-11-13 16:30:27 +01:00
import * as vscode from 'vscode' ;
const MEOW_COMMAND_ID = 'cat.meow' ;
2024-02-19 22:25:49 +00:00
interface ICatChatResult extends vscode . ChatResult {
2024-02-11 23:05:52 -03:00
metadata : {
command : string ;
}
2023-11-13 15:59:54 -06:00
}
2024-02-11 23:05:52 -03:00
const LANGUAGE_MODEL_ID = 'copilot-gpt-4' ;
2023-11-13 16:30:27 +01:00
export function activate ( context : vscode.ExtensionContext ) {
// Define a Cat chat agent handler.
2024-02-19 22:25:49 +00:00
const handler : vscode.ChatRequestHandler = async ( request : vscode.ChatRequest , context : vscode.ChatContext , stream : vscode.ChatResponseStream , token : vscode.CancellationToken ) : Promise < ICatChatResult > = > {
2024-01-18 20:00:07 -03:00
// To talk to an LLM in your subcommand handler implementation, your
2023-11-13 16:30:27 +01:00
// extension can use VS Code's `requestChatAccess` API to access the Copilot API.
2023-11-13 15:59:54 -06:00
// The GitHub Copilot Chat extension implements this provider.
2024-02-11 23:05:52 -03:00
if ( request . command == 'teach' ) {
2024-02-16 11:08:52 +01:00
const access = await vscode . lm . requestLanguageModelAccess ( LANGUAGE_MODEL_ID ) ;
2024-02-11 23:05:52 -03:00
const topics = [ 'linked list' , 'recursion' , 'stack' , 'queue' , 'pointers' ] ;
const topic = topics [ Math . floor ( Math . random ( ) * topics . length ) ] ;
2023-11-13 16:30:27 +01:00
const messages = [
2024-02-14 20:59:00 +00:00
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 )
2023-11-13 16:30:27 +01:00
] ;
2024-02-11 23:05:52 -03:00
const chatRequest = access . makeChatRequest ( messages , { } , token ) ;
for await ( const fragment of chatRequest . stream ) {
stream . markdown ( fragment ) ;
2023-11-13 16:30:27 +01:00
}
2024-02-11 23:05:52 -03:00
stream . button ( {
command : MEOW_COMMAND_ID ,
title : vscode.l10n.t ( 'Meow!' )
} ) ;
return { metadata : { command : 'teach' } } ;
} else if ( request . command == 'play' ) {
2024-02-16 11:08:52 +01:00
const access = await vscode . lm . requestLanguageModelAccess ( LANGUAGE_MODEL_ID ) ;
2023-11-13 16:30:27 +01:00
const messages = [
2024-02-22 15:30:48 +01:00
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 . ` ),
2024-02-14 20:59:00 +00:00
new vscode . LanguageModelUserMessage ( request . prompt )
2023-11-13 16:30:27 +01:00
] ;
2024-02-11 23:05:52 -03:00
const chatRequest = access . makeChatRequest ( messages , { } , token ) ;
for await ( const fragment of chatRequest . stream ) {
stream . markdown ( fragment ) ;
2023-11-13 16:30:27 +01:00
}
2024-02-11 23:05:52 -03:00
return { metadata : { command : 'play' } } ;
2023-11-13 15:59:54 -06:00
} else {
2024-02-16 11:08:52 +01:00
const access = await vscode . lm . requestLanguageModelAccess ( LANGUAGE_MODEL_ID ) ;
2024-02-11 23:05:52 -03:00
const messages = [
2024-02-22 15:30:48 +01:00
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.' ) ,
2024-02-14 20:59:00 +00:00
new vscode . LanguageModelUserMessage ( request . prompt )
2024-02-11 23:05:52 -03:00
] ;
const chatRequest = access . makeChatRequest ( messages , { } , token ) ;
for await ( const fragment of chatRequest . stream ) {
2024-02-22 15:30:48 +01:00
// 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 ) ;
2024-02-11 23:05:52 -03:00
}
return { metadata : { command : '' } } ;
}
2023-11-13 16:30:27 +01:00
} ;
2024-02-11 23:05:52 -03:00
2023-11-13 16:30:27 +01:00
// 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 `/`.
2024-02-19 22:25:49 +00:00
const agent = vscode . chat . createChatParticipant ( 'cat' , handler ) ;
2023-11-13 16:30:27 +01:00
agent . iconPath = vscode . Uri . joinPath ( context . extensionUri , 'cat.jpeg' ) ;
agent . description = vscode . l10n . t ( 'Meow! What can I help you with?' ) ;
2024-02-11 23:05:52 -03:00
agent . commandProvider = {
provideCommands ( token ) {
2023-11-13 16:30:27 +01:00
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 = {
2024-02-19 22:25:49 +00:00
provideFollowups ( result : ICatChatResult , token : vscode.CancellationToken ) {
2024-02-15 15:47:34 +01:00
return [ {
prompt : 'let us play' ,
2024-02-22 15:30:48 +01:00
label : vscode.l10n.t ( 'Play with the cat' ) ,
command : 'play'
2024-02-19 22:25:49 +00:00
} satisfies vscode . ChatFollowup ] ;
2023-11-13 16:30:27 +01:00
}
} ;
2024-02-19 22:25:49 +00:00
vscode . chat . registerChatVariableResolver ( 'cat_context' , 'Describes the state of mind and version of the cat' , {
2024-02-15 15:33:49 +01:00
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
}
]
}
}
} ) ;
2023-11-13 16:30:27 +01:00
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() { }