-
Notifications
You must be signed in to change notification settings - Fork 17
/
PromptHandlers.ts
146 lines (134 loc) · 5.47 KB
/
PromptHandlers.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import * as vscode from 'vscode';
import { AdaptiveCardTypes, Commands, ComponentTypes, ExtensionTypes, msSampleGalleryLink, promptCodeContext, promptContext, promptGeneralContext, promptNewContext, promptSetupContext } from '../constants';
import { ProjectInformation } from '../services/dataType/ProjectInformation';
export class PromptHandlers {
public static history: string[] = [];
public static previousCommand: string = '';
public static async handle(request: vscode.ChatRequest, context: vscode.ChatContext, stream: vscode.ChatResponseStream, token: vscode.CancellationToken): Promise<any> {
stream.progress(PromptHandlers.getRandomProgressMessage());
const chatCommand = (request.command && ['setup', 'new', 'code'].indexOf(request.command.toLowerCase()) > -1) ? request.command.toLowerCase() : '';
const messages: vscode.LanguageModelChatMessage[] = [];
messages.push(vscode.LanguageModelChatMessage.Assistant(promptContext));
messages.push(vscode.LanguageModelChatMessage.Assistant(PromptHandlers.getChatCommandPrompt(chatCommand)));
if (PromptHandlers.previousCommand !== chatCommand) {
PromptHandlers.history = [];
PromptHandlers.previousCommand = chatCommand;
} else {
PromptHandlers.history.forEach(message => messages.push(vscode.LanguageModelChatMessage.Assistant(message)));
}
messages.push(vscode.LanguageModelChatMessage.User(request.prompt));
PromptHandlers.history.push(request.prompt);
const [model] = await vscode.lm.selectChatModels({ vendor: 'copilot', family: 'gpt-4o' });
try {
const chatResponse = await model.sendRequest(messages, {}, token);
let query = '';
for await (const fragment of chatResponse.text) {
query += fragment;
stream.markdown(fragment);
}
PromptHandlers.history.push(query);
PromptHandlers.getChatCommandButtons(chatCommand, query).forEach(button => stream.button(button));
return { metadata: { command: chatCommand } };
} catch (err) {
if (err instanceof vscode.LanguageModelError) {
if (err.message.includes('off_topic')) {
stream.markdown('...I am sorry, I am not able to help with that. Please try again with a different question.');
}
} else {
stream.markdown('...It seems that something is not working as expected. Please try again later.');
}
return { metadata: { command: '' } };
}
}
private static getChatCommandPrompt(chatCommand: string): string {
let context: string = '';
switch (chatCommand) {
case 'setup':
context += promptSetupContext;
case 'new':
context += promptNewContext;
context += `\n Here is some more information regarding each component type ${ComponentTypes}`;
context += `\n Here is some more information regarding each extension type ${ExtensionTypes}`;
context += `\n Here is some more information regarding each ACE type ${AdaptiveCardTypes}`;
case 'code':
context += promptCodeContext;
default:
context += promptGeneralContext;
}
return context;
}
private static getRandomProgressMessage(): string {
const messages = [
'Checking...',
'Let me think about it...',
'Reading the docs...',
'Cracking the code...',
'Unleashing the algorithms...',
'Beaming up the data...',
'Feeding the hamsters...',
'Charging the flux capacitor...',
'Warming up the servers...',
'Consulting with the rubber duck...',
'Asking the magic 8-ball...',
'Counting backwards from infinity...',
'Commencing time travel...',
'Converting coffee to code...',
'Adjusting the reality matrix...',
'Waking up the AI...'
];
return messages[Math.floor(Math.random() * messages.length)];
}
private static getChatCommandButtons(chatCommand: string, chatResponse: string) {
switch (chatCommand) {
case 'new':
const buttons = [];
const regex = /```([^\n]*)\n(?=[\s\S]*?yo @microsoft\/sharepoint.+)([\s\S]*?)\n?```/g;
const match = regex.exec(chatResponse);
if (match && match[2]) {
buttons.push(
{
command: Commands.createProjectCopilot,
title: vscode.l10n.t('Create project'),
arguments: [match[2]],
});
}
if (chatResponse.toLowerCase().includes(msSampleGalleryLink)) {
buttons.push({
command: Commands.samplesGallery,
title: vscode.l10n.t('Open sample gallery'),
});
}
return buttons;
case 'setup':
if (chatResponse.toLowerCase().includes('check dependencies')) {
return[{
command: Commands.checkDependencies,
title: vscode.l10n.t('Check if my local workspace is ready'),
}];
}
return [];
case 'code':
if (ProjectInformation.isSPFxProject) {
return [{
command: Commands.upgradeProject,
title: vscode.l10n.t('Get upgrade guidance to latest SPFx version'),
},
{
command: Commands.validateProject,
title: vscode.l10n.t('Validate your project'),
},
{
command: Commands.renameProject,
title: vscode.l10n.t('Rename your project'),
},
{
command: Commands.pipeline,
title: vscode.l10n.t('Create a CI/CD workflow'),
}];
}
return [];
default:
return [];
}
}
}