Compare commits

...

1 Commits

Author SHA1 Message Date
Elio Struyf
301814bcdd #816 - Sample implementation 2024-06-06 17:13:03 +02:00
5 changed files with 178 additions and 9 deletions

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 26.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 1250 1250" style="enable-background:new 0 0 1250 1250;" xml:space="preserve">
<path fill="#02aeb7" d="M316,1082.3H119.4V151.2h347.5v218.9H316v135.7h140.5v210.5H316V1082.3z"/>
<path fill="#02aeb7" d="M602.2,151.2H704l77.7,379.9c9.5,47.4,18.1,95,26,142.6s15,97.6,21.4,149.8c0.7-6.8,1.3-12.1,1.7-16
c0.2-2.7,0.6-5.5,1.1-8.2l16.6-106.7l14.9-101.3l13.2-66.9l69.2-373.3h102.9l81.2,931.1h-113.6l-19.9-316c-0.8-16.1-1.4-29.9-2-41.6
c-0.6-11.7-0.9-21.3-0.9-29L988.3,571l-2.8-114.6c0-0.8,0-2.5-0.3-5.1s-0.5-6.1-0.9-10.6l-2.8,18.7c-3,22.1-5.8,41.4-8.3,57.9
s-4.7,30.3-6.6,41.6l-15.1,84.9l-5.7,32l-74.3,406.4h-80.1l-69.7-351c-9.5-46.2-17.9-93.1-25.4-140.8s-14.2-97.6-20.3-149.9
l-34.3,641.6H529.6L602.2,151.2z"/>
<rect x="119.4" y="0.1" fill="#02aeb7" width="184" height="64.7"/>
<rect x="395.7" y="0.1" fill="#02aeb7" width="184" height="64.7"/>
<rect x="675.3" y="0.1" fill="#02aeb7" width="184" height="64.7"/>
<rect x="119.4" y="1184.7" fill="#02aeb7" width="184" height="64.7"/>
<rect x="395.7" y="1184.7" fill="#02aeb7" width="184" height="64.7"/>
<rect x="675.3" y="1184.7" fill="#02aeb7" width="184" height="64.7"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

10
package-lock.json generated
View File

@@ -33,7 +33,7 @@
"@types/react": "17.0.0",
"@types/react-datepicker": "^4.8.0",
"@types/react-dom": "17.0.0",
"@types/vscode": "^1.73.0",
"@types/vscode": "^1.90.0",
"@typescript-eslint/eslint-plugin": "^5.50.0",
"@typescript-eslint/parser": "^5.50.0",
"@vscode-elements/elements": "^1.2.0",
@@ -110,7 +110,7 @@
"yawn-yaml": "^1.5.0"
},
"engines": {
"vscode": "^1.73.0"
"vscode": "^1.90.0"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@@ -2084,9 +2084,9 @@
"dev": true
},
"node_modules/@types/vscode": {
"version": "1.86.0",
"resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.86.0.tgz",
"integrity": "sha512-DnIXf2ftWv+9LWOB5OJeIeaLigLHF7fdXF6atfc7X5g2w/wVZBgk0amP7b+ub5xAuW1q7qP5YcFvOcit/DtyCQ==",
"version": "1.90.0",
"resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.90.0.tgz",
"integrity": "sha512-oT+ZJL7qHS9Z8bs0+WKf/kQ27qWYR3trsXpq46YDjFqBsMLG4ygGGjPaJ2tyrH0wJzjOEmDyg9PDJBBhWg9pkQ==",
"dev": true
},
"node_modules/@types/vscode-webview": {

View File

@@ -26,10 +26,13 @@
},
"qna": "https://github.com/estruyf/vscode-front-matter/discussions",
"engines": {
"vscode": "^1.73.0"
"vscode": "^1.90.0"
},
"l10n": "./l10n",
"categories": [
"AI",
"Chat",
"Visualization",
"Other"
],
"keywords": [
@@ -69,6 +72,21 @@
"**/.frontmatter/config/*.json": "jsonc"
}
},
"chatParticipants": [{
"id": "frontMatter.chat",
"name": "fm",
"fullName": "Front Matter",
"description": "Front Matter CMS chat",
"isSticky": true,
"commands": [{
"name": "docs",
"description": "Ask a question about Front Matter CMS and we will try to help you out."
}, {
"name": "create",
"description": "Create a new Front Matter CMS project.",
"isSticky": true
}]
}],
"keybindings": [{
"command": "frontMatter.dashboard",
"key": "alt+d"
@@ -2768,7 +2786,7 @@
"@types/react": "17.0.0",
"@types/react-datepicker": "^4.8.0",
"@types/react-dom": "17.0.0",
"@types/vscode": "^1.73.0",
"@types/vscode": "^1.90.0",
"@typescript-eslint/eslint-plugin": "^5.50.0",
"@typescript-eslint/parser": "^5.50.0",
"@vscode-elements/elements": "^1.2.0",

View File

@@ -1,14 +1,99 @@
import { Telemetry } from './../helpers/Telemetry';
import { TelemetryEvent, PreviewCommands, GeneralCommands } from './../constants';
import { TelemetryEvent, PreviewCommands, GeneralCommands, WEBSITE_LINKS, COMMAND_NAME } from './../constants';
import { join } from 'path';
import { commands, Uri, ViewColumn, window } from 'vscode';
import {
CancellationToken,
chat,
ChatContext,
ChatRequest,
ChatResponseStream,
commands,
LanguageModelChatMessage,
lm,
Uri,
ViewColumn,
window
} from 'vscode';
import { Extension } from '../helpers';
import { WebviewHelper } from '@estruyf/vscode';
import { getLocalizationFile } from '../utils/getLocalizationFile';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
import { Folders } from '.';
export class Chatbot {
private static company: string;
private static chatId: number;
public static async register() {
const fmChat = chat.createChatParticipant('frontMatter.chat', this.handler);
fmChat.iconPath = Uri.joinPath(
Extension.getInstance().extensionPath,
'/assets/icons/frontmatter-short-teal.svg'
);
}
private static async handler(
request: ChatRequest,
context: ChatContext,
stream: ChatResponseStream,
token: CancellationToken
) {
const { command, prompt } = request;
if (command === 'docs' && prompt) {
if (!this.chatId || !this.company) {
stream.progress('Initializing the Front Matter AI...');
await this.initChat();
}
if (!this.company || !this.chatId) {
this.showAiError(stream);
return;
}
stream.progress('Fetching information from the docs...');
const data: {
answer: string;
answerId: number;
sources: string[];
} = await this.retrieveDocs(prompt);
if (!data.answer) {
this.showAiError(stream);
return;
}
stream.markdown(data.answer);
} else if (command === 'create') {
stream.progress(`Checking your configuration...`);
const messages = [LanguageModelChatMessage.User(`You are a kind and helpful assistant named Front Matter AI. You aim to provide support in managing Front Matter CMS and its content. If you don't know the answer to a question, you will guide the user to the documentation (https://frontmatter.codes/docs). You can use the "https://frontmatter.codes/docs" link as a reference. When returning code you will surround it in a MD code block, not HTML.`)];
messages.push(LanguageModelChatMessage.User(request.prompt));
const [model] = await lm.selectChatModels({ vendor: 'copilot', family: 'gpt-4' });
try {
const chatResponse = await model.sendRequest(messages, {}, token);
for await (const fragment of chatResponse.text) {
stream.markdown(fragment);
}
stream.button({
command: COMMAND_NAME.createByContentType,
title: 'Create new content',
});
} catch (err) {
this.showAiError(stream);
return;
}
} else {
stream.markdown('Sorry, I do not understand that command. Check out the [Front Matter CMS](https://frontmatter.codes/docs) documentation for more information.')
}
}
/**
* Open the Chatbot in the editor
*/
@@ -119,4 +204,50 @@ export class Chatbot {
Telemetry.send(TelemetryEvent.openChatbot);
}
private static async initChat() {
const response = await fetch(`${WEBSITE_LINKS.root}/api/ai-init`);
if (!response.ok) {
return;
}
const data = await response.json();
if (!data.company || !data.chatId) {
return;
}
this.company = data.company;
this.chatId = data.chatId;
}
private static async retrieveDocs(prompt: string) {
if (!this.company || !this.chatId) {
return;
}
const response = await fetch(`${WEBSITE_LINKS.root}/api/ai-chat`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'accept': '*',
},
body: JSON.stringify({
company: this.company,
chatId: this.chatId,
question: prompt,
}),
});
if (!response.ok) {
return;
}
return await response.json();
}
private static showAiError(stream: ChatResponseStream) {
stream.markdown(`Sorry, I am not able to connect to the Front Matter AI service. Please try again later or check out the [Front Matter CMS](https://frontmatter.codes/docs) documentation.`);
}
}

View File

@@ -241,6 +241,9 @@ export async function activate(context: vscode.ExtensionContext) {
// Cache commands
Cache.registerCommands();
// GitHub Copilot integration
Chatbot.register();
// Subscribe all commands
subscriptions.push(insertTags, PanelView, insertCategories, collapseAll, fmStatusBarItem);