Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
217 changes: 207 additions & 10 deletions demo/src/features/ai.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ExtensionHostKind, registerExtension } from '@codingame/monaco-vscode-api/extensions'
import * as vscode from 'vscode'

const { getApi } = registerExtension(
{
Expand All @@ -9,37 +10,233 @@ const { getApi } = registerExtension(
vscode: '*'
},
contributes: {
configuration: {
title: 'Codingame AI Demo',
properties: {
codingameAICompletionsEnabled: {
type: 'object',
scope: 'window',
default: {
'*': true,
plaintext: false,
markdown: false,
scminput: false
},
additionalProperties: {
type: 'boolean'
},
markdownDescription:
'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 + \\`'
},
codingameNextEditSuggestionsEnabled: {
type: 'boolean',
default: true,
tags: ['nextEditSuggestions', 'onExp'],
scope: 'language-overridable'
}
}
},
commands: [
{
command: 'aiSuggestedCommand',
title: 'This is a command suggested by the AI'
}
],
chatParticipants: [
{
id: 'codingame.aiDemo.participant',
fullName: 'Codingame AI',
name: 'codingame-ai',
isDefault: true,
modes: ['agent']
}
],
languageModelChatProviders: [
{
vendor: 'coddingame.aiDemo.modelProvider',
displayName: 'Codingame provider'
}
],
languageModelTools: [
{
name: 'codingame-tool',
toolReferenceName: 'codingame-tool',
displayName: 'Codingame tool',
userDescription: 'A tool that multiply a number by two',
modelDescription: 'Use this tool to get the result of a multiplication by two',
canBeReferencedInPrompt: true,
inputSchema: {
type: 'object',
properties: {
value: {
type: 'number'
}
},
required: ['value'],
additionalProperties: false
}
}
]
},
enabledApiProposals: ['aiRelatedInformation']
enabledApiProposals: [
'aiRelatedInformation',
'mappedEditsProvider',
'chatSessionsProvider',
'defaultChatParticipant',
'chatParticipantAdditions',
'chatParticipantPrivate',
'languageModelThinkingPart'
]
},
ExtensionHostKind.LocalProcess,
{
system: true // to be able to use api proposals
}
)

void getApi().then(async (vscode) => {
vscode.commands.registerCommand('aiSuggestedCommand', () => {
void vscode.window.showInformationMessage('Hello', {
void getApi().then(async (vscodeApi) => {
vscodeApi.commands.registerCommand('aiSuggestedCommand', () => {
void vscodeApi.window.showInformationMessage('Hello', {
detail: 'You just run the AI suggested command',
modal: true
})
})
vscode.ai.registerRelatedInformationProvider(vscode.RelatedInformationType.CommandInformation, {
provideRelatedInformation() {
vscodeApi.ai.registerRelatedInformationProvider(
vscodeApi.RelatedInformationType.CommandInformation,
{
provideRelatedInformation() {
return [
{
type: vscode.RelatedInformationType.CommandInformation,
command: 'aiSuggestedCommand',
weight: 9999
}
]
}
}
)

interface CodingameToolParameters {
value: number
}

class CodingameTool implements vscode.LanguageModelTool<CodingameToolParameters> {
async invoke(
options: vscode.LanguageModelToolInvocationPrepareOptions<CodingameToolParameters>
) {
return new vscode.LanguageModelToolResult([
new vscode.LanguageModelTextPart('The result is: ' + options.input.value * 2)
])
}

async prepareInvocation(
options: vscode.LanguageModelToolInvocationPrepareOptions<CodingameToolParameters>
): Promise<vscode.PreparedToolInvocation> {
const confirmationMessages = {
title: vscode.l10n.t('Use Codingame tool'),
message: new vscode.MarkdownString(
'AI wants to get the double of `' + options.input.value + '`'
)
}

return {
invocationMessage: new vscode.MarkdownString(
'Doubling the value `' + options.input.value + '`'
),
confirmationMessages
}
}
}

vscodeApi.lm.registerTool('codingame-tool', new CodingameTool())

const _onDidChangeLanguageModelChatInformation = new vscodeApi.EventEmitter<void>()

vscodeApi.lm.registerLanguageModelChatProvider('coddingame.aiDemo.modelProvider', {
provideLanguageModelChatInformation() {
return [
{
type: vscode.RelatedInformationType.CommandInformation,
command: 'aiSuggestedCommand',
weight: 9999
id: 'codingame',
capabilities: {
toolCalling: true
},
family: 'codingame',
maxInputTokens: 1000000,
maxOutputTokens: 1000000,
name: 'Codingame',
version: '1.0.0',
isDefault: true,
isUserSelectable: true
}
]
}
},
async provideTokenCount() {
return 0
},
async provideLanguageModelChatResponse(
_model,
_messages,
_options,
progress: vscode.Progress<vscode.LanguageModelResponsePart2>
) {
progress.report(new vscode.LanguageModelThinkingPart('Think', 'thinkId'))
await new Promise((resolve) => setTimeout(resolve, 300))
progress.report(new vscode.LanguageModelThinkingPart('ing...', 'thinkId'))
await new Promise((resolve) => setTimeout(resolve, 1000))
progress.report(
new vscode.LanguageModelToolCallPart('callId', 'codingame-tool', { value: 21 })
)
await new Promise((resole) => setTimeout(resole, 2000))
progress.report(new vscode.LanguageModelTextPart('Tool'))
await new Promise((resole) => setTimeout(resole, 300))
progress.report(new vscode.LanguageModelTextPart(' called\n'))
},
onDidChangeLanguageModelChatInformation: _onDidChangeLanguageModelChatInformation.event
})

_onDidChangeLanguageModelChatInformation.fire()

vscodeApi.chat.createChatParticipant(
'codingame.aiDemo.participant',
async (
request: vscode.ChatRequest,
_context: vscode.ChatContext,
response: vscode.ChatResponseStream
) => {
const modelResponse = await request.model.sendRequest([
vscodeApi.LanguageModelChatMessage.User(request.prompt)
])
for await (const part of modelResponse.stream) {
if (part instanceof vscode.LanguageModelTextPart) {
response.markdown(part.value)
} else if (part instanceof vscode.LanguageModelThinkingPart) {
response.thinkingProgress({
id: part.id,
text: part.value,
metadata: part.metadata
})
} else if (part instanceof vscode.LanguageModelToolCallPart) {
const res = await vscode.lm.invokeTool(part.name, {
toolInvocationToken: request.toolInvocationToken,
input: part.input
})
let toolResult = ''
for (const toolPart of res.content) {
if (toolPart instanceof vscode.LanguageModelTextPart) {
toolResult += toolPart.value
}
}
response.markdown('Tool result: `' + toolResult + '`\n')
}
}

const firstFile = request.references[0]?.value
if (firstFile != null && firstFile instanceof vscodeApi.Uri) {
response.textEdit(
request.references[0]!.value as vscode.Uri,
vscodeApi.TextEdit.replace(new vscodeApi.Range(5, 0, 7, 0), 'Hello world')
)
}
}
)
})
32 changes: 32 additions & 0 deletions demo/src/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,38 @@ if (locale != null) {
const mode = searchParams.get('mode')
const sandboxed = searchParams.has('sandboxed')

declare global {
interface Window {
_VSCODE_PRODUCT_JSON: object
}
}

window._VSCODE_PRODUCT_JSON = {
defaultChatAgent: {
chatExtensionId: 'codingame.aiDemo',
extensionId: '',
completionsEnablementSetting: 'codingameAICompletionsEnabled',
nextEditSuggestionsSetting: 'codingameNextEditSuggestionsEnabled',
provider: {
default: {
id: 'codingame',
name: 'Codingame'
},
apple: {
id: 'codingame',
name: 'Codingame'
},
enterprise: {
id: 'codingame',
name: 'Codingame'
},
google: {
id: 'codingame',
name: 'Codingame'
}
}
}
}
;(async () => {
if (sandboxed) {
window.vscodeContainer = await new Promise<HTMLElement>((resolve) => {
Expand Down
20 changes: 18 additions & 2 deletions demo/src/setup.common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ import getWorkspaceTrustOverride from '@codingame/monaco-vscode-workspace-trust-
import getLogServiceOverride from '@codingame/monaco-vscode-log-service-override'
import getWorkingCopyServiceOverride from '@codingame/monaco-vscode-working-copy-service-override'
import getTestingServiceOverride from '@codingame/monaco-vscode-testing-service-override'
import getChatServiceOverride from '@codingame/monaco-vscode-chat-service-override'
import getChatServiceOverride, {
ChatEntitlement
} from '@codingame/monaco-vscode-chat-service-override'
import getNotebookServiceOverride from '@codingame/monaco-vscode-notebook-service-override'
import getWelcomeServiceOverride from '@codingame/monaco-vscode-welcome-service-override'
import getWalkThroughServiceOverride from '@codingame/monaco-vscode-walkthrough-service-override'
Expand Down Expand Up @@ -443,7 +445,21 @@ export const commonServices: IEditorOverrideServices = {
...getWorkingCopyServiceOverride(),
...getScmServiceOverride(),
...getTestingServiceOverride(),
...getChatServiceOverride(),
...getChatServiceOverride({
customEntitlement: {
anonymous: false,
entitlement: ChatEntitlement.Enterprise,
previewFeaturesDisabled: false,
quotas: {},
sentiment: {
installed: true,
hidden: false,
disabled: false,
untrusted: false,
registered: false
}
}
}),
...getNotebookServiceOverride(),
...getWelcomeServiceOverride(),
...getWalkThroughServiceOverride(),
Expand Down
Loading
Loading