Skip to content

Commit 815ed88

Browse files
authored
Merge pull request #778 from CodinGame/ohr/chat-in-demo
[DEMO] add chat examples
2 parents 712da31 + 61eae81 commit 815ed88

6 files changed

Lines changed: 358 additions & 21 deletions

File tree

demo/src/features/ai.ts

Lines changed: 207 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ExtensionHostKind, registerExtension } from '@codingame/monaco-vscode-api/extensions'
2+
import * as vscode from 'vscode'
23

34
const { getApi } = registerExtension(
45
{
@@ -9,37 +10,233 @@ const { getApi } = registerExtension(
910
vscode: '*'
1011
},
1112
contributes: {
13+
configuration: {
14+
title: 'Codingame AI Demo',
15+
properties: {
16+
codingameAICompletionsEnabled: {
17+
type: 'object',
18+
scope: 'window',
19+
default: {
20+
'*': true,
21+
plaintext: false,
22+
markdown: false,
23+
scminput: false
24+
},
25+
additionalProperties: {
26+
type: 'boolean'
27+
},
28+
markdownDescription:
29+
'Enable or disable auto triggering of Copilot completions for specified [languages](https://code.visualstudio.com/docs/languages/identifiers). You can still trigger suggestions manually using `Alt + \\`'
30+
},
31+
codingameNextEditSuggestionsEnabled: {
32+
type: 'boolean',
33+
default: true,
34+
tags: ['nextEditSuggestions', 'onExp'],
35+
scope: 'language-overridable'
36+
}
37+
}
38+
},
1239
commands: [
1340
{
1441
command: 'aiSuggestedCommand',
1542
title: 'This is a command suggested by the AI'
1643
}
44+
],
45+
chatParticipants: [
46+
{
47+
id: 'codingame.aiDemo.participant',
48+
fullName: 'Codingame AI',
49+
name: 'codingame-ai',
50+
isDefault: true,
51+
modes: ['agent']
52+
}
53+
],
54+
languageModelChatProviders: [
55+
{
56+
vendor: 'coddingame.aiDemo.modelProvider',
57+
displayName: 'Codingame provider'
58+
}
59+
],
60+
languageModelTools: [
61+
{
62+
name: 'codingame-tool',
63+
toolReferenceName: 'codingame-tool',
64+
displayName: 'Codingame tool',
65+
userDescription: 'A tool that multiply a number by two',
66+
modelDescription: 'Use this tool to get the result of a multiplication by two',
67+
canBeReferencedInPrompt: true,
68+
inputSchema: {
69+
type: 'object',
70+
properties: {
71+
value: {
72+
type: 'number'
73+
}
74+
},
75+
required: ['value'],
76+
additionalProperties: false
77+
}
78+
}
1779
]
1880
},
19-
enabledApiProposals: ['aiRelatedInformation']
81+
enabledApiProposals: [
82+
'aiRelatedInformation',
83+
'mappedEditsProvider',
84+
'chatSessionsProvider',
85+
'defaultChatParticipant',
86+
'chatParticipantAdditions',
87+
'chatParticipantPrivate',
88+
'languageModelThinkingPart'
89+
]
2090
},
2191
ExtensionHostKind.LocalProcess,
2292
{
2393
system: true // to be able to use api proposals
2494
}
2595
)
2696

27-
void getApi().then(async (vscode) => {
28-
vscode.commands.registerCommand('aiSuggestedCommand', () => {
29-
void vscode.window.showInformationMessage('Hello', {
97+
void getApi().then(async (vscodeApi) => {
98+
vscodeApi.commands.registerCommand('aiSuggestedCommand', () => {
99+
void vscodeApi.window.showInformationMessage('Hello', {
30100
detail: 'You just run the AI suggested command',
31101
modal: true
32102
})
33103
})
34-
vscode.ai.registerRelatedInformationProvider(vscode.RelatedInformationType.CommandInformation, {
35-
provideRelatedInformation() {
104+
vscodeApi.ai.registerRelatedInformationProvider(
105+
vscodeApi.RelatedInformationType.CommandInformation,
106+
{
107+
provideRelatedInformation() {
108+
return [
109+
{
110+
type: vscode.RelatedInformationType.CommandInformation,
111+
command: 'aiSuggestedCommand',
112+
weight: 9999
113+
}
114+
]
115+
}
116+
}
117+
)
118+
119+
interface CodingameToolParameters {
120+
value: number
121+
}
122+
123+
class CodingameTool implements vscode.LanguageModelTool<CodingameToolParameters> {
124+
async invoke(
125+
options: vscode.LanguageModelToolInvocationPrepareOptions<CodingameToolParameters>
126+
) {
127+
return new vscode.LanguageModelToolResult([
128+
new vscode.LanguageModelTextPart('The result is: ' + options.input.value * 2)
129+
])
130+
}
131+
132+
async prepareInvocation(
133+
options: vscode.LanguageModelToolInvocationPrepareOptions<CodingameToolParameters>
134+
): Promise<vscode.PreparedToolInvocation> {
135+
const confirmationMessages = {
136+
title: vscode.l10n.t('Use Codingame tool'),
137+
message: new vscode.MarkdownString(
138+
'AI wants to get the double of `' + options.input.value + '`'
139+
)
140+
}
141+
142+
return {
143+
invocationMessage: new vscode.MarkdownString(
144+
'Doubling the value `' + options.input.value + '`'
145+
),
146+
confirmationMessages
147+
}
148+
}
149+
}
150+
151+
vscodeApi.lm.registerTool('codingame-tool', new CodingameTool())
152+
153+
const _onDidChangeLanguageModelChatInformation = new vscodeApi.EventEmitter<void>()
154+
155+
vscodeApi.lm.registerLanguageModelChatProvider('coddingame.aiDemo.modelProvider', {
156+
provideLanguageModelChatInformation() {
36157
return [
37158
{
38-
type: vscode.RelatedInformationType.CommandInformation,
39-
command: 'aiSuggestedCommand',
40-
weight: 9999
159+
id: 'codingame',
160+
capabilities: {
161+
toolCalling: true
162+
},
163+
family: 'codingame',
164+
maxInputTokens: 1000000,
165+
maxOutputTokens: 1000000,
166+
name: 'Codingame',
167+
version: '1.0.0',
168+
isDefault: true,
169+
isUserSelectable: true
41170
}
42171
]
43-
}
172+
},
173+
async provideTokenCount() {
174+
return 0
175+
},
176+
async provideLanguageModelChatResponse(
177+
_model,
178+
_messages,
179+
_options,
180+
progress: vscode.Progress<vscode.LanguageModelResponsePart2>
181+
) {
182+
progress.report(new vscode.LanguageModelThinkingPart('Think', 'thinkId'))
183+
await new Promise((resolve) => setTimeout(resolve, 300))
184+
progress.report(new vscode.LanguageModelThinkingPart('ing...', 'thinkId'))
185+
await new Promise((resolve) => setTimeout(resolve, 1000))
186+
progress.report(
187+
new vscode.LanguageModelToolCallPart('callId', 'codingame-tool', { value: 21 })
188+
)
189+
await new Promise((resole) => setTimeout(resole, 2000))
190+
progress.report(new vscode.LanguageModelTextPart('Tool'))
191+
await new Promise((resole) => setTimeout(resole, 300))
192+
progress.report(new vscode.LanguageModelTextPart(' called\n'))
193+
},
194+
onDidChangeLanguageModelChatInformation: _onDidChangeLanguageModelChatInformation.event
44195
})
196+
197+
_onDidChangeLanguageModelChatInformation.fire()
198+
199+
vscodeApi.chat.createChatParticipant(
200+
'codingame.aiDemo.participant',
201+
async (
202+
request: vscode.ChatRequest,
203+
_context: vscode.ChatContext,
204+
response: vscode.ChatResponseStream
205+
) => {
206+
const modelResponse = await request.model.sendRequest([
207+
vscodeApi.LanguageModelChatMessage.User(request.prompt)
208+
])
209+
for await (const part of modelResponse.stream) {
210+
if (part instanceof vscode.LanguageModelTextPart) {
211+
response.markdown(part.value)
212+
} else if (part instanceof vscode.LanguageModelThinkingPart) {
213+
response.thinkingProgress({
214+
id: part.id,
215+
text: part.value,
216+
metadata: part.metadata
217+
})
218+
} else if (part instanceof vscode.LanguageModelToolCallPart) {
219+
const res = await vscode.lm.invokeTool(part.name, {
220+
toolInvocationToken: request.toolInvocationToken,
221+
input: part.input
222+
})
223+
let toolResult = ''
224+
for (const toolPart of res.content) {
225+
if (toolPart instanceof vscode.LanguageModelTextPart) {
226+
toolResult += toolPart.value
227+
}
228+
}
229+
response.markdown('Tool result: `' + toolResult + '`\n')
230+
}
231+
}
232+
233+
const firstFile = request.references[0]?.value
234+
if (firstFile != null && firstFile instanceof vscodeApi.Uri) {
235+
response.textEdit(
236+
request.references[0]!.value as vscode.Uri,
237+
vscodeApi.TextEdit.replace(new vscodeApi.Range(5, 0, 7, 0), 'Hello world')
238+
)
239+
}
240+
}
241+
)
45242
})

demo/src/loader.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,38 @@ if (locale != null) {
5858
const mode = searchParams.get('mode')
5959
const sandboxed = searchParams.has('sandboxed')
6060

61+
declare global {
62+
interface Window {
63+
_VSCODE_PRODUCT_JSON: object
64+
}
65+
}
66+
67+
window._VSCODE_PRODUCT_JSON = {
68+
defaultChatAgent: {
69+
chatExtensionId: 'codingame.aiDemo',
70+
extensionId: '',
71+
completionsEnablementSetting: 'codingameAICompletionsEnabled',
72+
nextEditSuggestionsSetting: 'codingameNextEditSuggestionsEnabled',
73+
provider: {
74+
default: {
75+
id: 'codingame',
76+
name: 'Codingame'
77+
},
78+
apple: {
79+
id: 'codingame',
80+
name: 'Codingame'
81+
},
82+
enterprise: {
83+
id: 'codingame',
84+
name: 'Codingame'
85+
},
86+
google: {
87+
id: 'codingame',
88+
name: 'Codingame'
89+
}
90+
}
91+
}
92+
}
6193
;(async () => {
6294
if (sandboxed) {
6395
window.vscodeContainer = await new Promise<HTMLElement>((resolve) => {

demo/src/setup.common.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ import getWorkspaceTrustOverride from '@codingame/monaco-vscode-workspace-trust-
5252
import getLogServiceOverride from '@codingame/monaco-vscode-log-service-override'
5353
import getWorkingCopyServiceOverride from '@codingame/monaco-vscode-working-copy-service-override'
5454
import getTestingServiceOverride from '@codingame/monaco-vscode-testing-service-override'
55-
import getChatServiceOverride from '@codingame/monaco-vscode-chat-service-override'
55+
import getChatServiceOverride, {
56+
ChatEntitlement
57+
} from '@codingame/monaco-vscode-chat-service-override'
5658
import getNotebookServiceOverride from '@codingame/monaco-vscode-notebook-service-override'
5759
import getWelcomeServiceOverride from '@codingame/monaco-vscode-welcome-service-override'
5860
import getWalkThroughServiceOverride from '@codingame/monaco-vscode-walkthrough-service-override'
@@ -443,7 +445,21 @@ export const commonServices: IEditorOverrideServices = {
443445
...getWorkingCopyServiceOverride(),
444446
...getScmServiceOverride(),
445447
...getTestingServiceOverride(),
446-
...getChatServiceOverride(),
448+
...getChatServiceOverride({
449+
customEntitlement: {
450+
anonymous: false,
451+
entitlement: ChatEntitlement.Enterprise,
452+
previewFeaturesDisabled: false,
453+
quotas: {},
454+
sentiment: {
455+
installed: true,
456+
hidden: false,
457+
disabled: false,
458+
untrusted: false,
459+
registered: false
460+
}
461+
}
462+
}),
447463
...getNotebookServiceOverride(),
448464
...getWelcomeServiceOverride(),
449465
...getWalkThroughServiceOverride(),

0 commit comments

Comments
 (0)