Merge pull request #27 from devchat-ai/feat/welcome_commands

Feat/welcome commands
This commit is contained in:
Rankin Zheng 2024-02-02 19:50:49 +08:00 committed by GitHub
commit 67fe833c53
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 63 additions and 126 deletions

View File

@ -188,15 +188,6 @@ const InputMessage = observer((props: any) => {
};
useEffect(() => {
input.fetchContextMenus().then();
input.fetchCommandMenus().then();
input.fetchModelMenus().then();
messageUtil.registerHandler(
"regCommandList",
(message: { result: object[] }) => {
input.updateCommands(message.result);
}
);
messageUtil.registerHandler(
"chatWithDevChat",
(message: { command: string; message: string }) => {

View File

@ -77,69 +77,6 @@ const MessageMarkdown = observer((props: MessageMarkdownProps) => {
const { i18n, t } = useTranslation();
const platform = process.env.platform;
const handleExplain = (value: string | undefined) => {
switch (value) {
case "#ask_code":
chat.addMessages([
Message.create({
type: "user",
message: "Explain /ask-code",
}),
Message.create({
type: "bot",
message: `***/ask-code***
Ask anything about your codebase and get answers from our AI agent.
DevChat intelligently navigates your codebase using GPT-4. It automatically selects and analyzes up to ten most relevant source files to answer your question. Stay tuned we're soon integrating the more cost-efficient LLama 2 - 70B model.
Sample questions:
- Why does the lead time for changes sometimes show as null?
- How is store.findAllAccounts implemented?
- The recursive retriever currently drops any TextNodes and only queries the IndexNodes. It's a bug. How can we fix it?
`,
}),
]);
break;
case "#code":
chat.addMessages([
Message.create({
type: "user",
message: "Explain /code",
}),
Message.create({
type: "bot",
message: `***/code***
Use this DevChat workflow to request code writing. Please input your specific requirements and supply the appropriate context for implementation. You can select the relevant code or files and right-click to "Add to DevChat". If you find the context is still insufficient, you can enhance my understanding of your code by providing class/function definitions of the selected code. To do this, click the "+" button for the selected code and choose "symbol definitions". Please note, it may take a few seconds for this information to appear in DevChat.
`,
}),
]);
break;
case "#release_note":
chat.addMessages([
Message.create({
type: "user",
message: "Explain /release_note",
}),
Message.create({
type: "bot",
message: `***/release_note***
Generate a professionally written and formatted release note in markdown with this workflow. I just need some basic information about the commits for the release. Add this to the context by clicking the "+" button and selecting \`git_log_releasenote\`. If the scope of commits differs from the default command, you can also select \`<custom command>\` and input a command line such as \`git log 579398b^..HEAD --pretty=format:"%h - %B"\` to include the commit 579398b (inclusive) up to the latest.
`,
}),
]);
break;
case "#settings":
messageUtil.sendMessage({
command: "doCommand",
content: ["workbench.action.openSettings", "@ext:merico.devchat"],
});
break;
}
chat.goScrollBottom();
};
const handleButton = (
value: string | number | readonly string[] | undefined
) => {
@ -223,8 +160,8 @@ Generate a professionally written and formatted release note in markdown with th
if (i18n && i18n.language === "zh") {
// 目前只有中文需要单独翻译
if (children) {
if (children.includes("You can configure DevChat from")) {
return t("devchat.help");
if (children.includes("Do you want to write some code or have a question about the project? ")) {
return t("devchat.help") + chat.helpWorkflowCommands();
}
if (
children.includes(
@ -440,20 +377,14 @@ Generate a professionally written and formatted release note in markdown with th
);
},
a({ node, className, children, href, ...props }) {
const customAnchors = [
"#code",
"#commit_message",
"#release_note",
"#ask_code",
"#extension",
"#settings",
].filter((item) => item === href);
return customAnchors.length > 0 ? (
return className === "workflow_command" ? (
<Anchor
className={classes.link}
href={href}
href="javascript:void()"
onClick={() => {
handleExplain(href);
if(href){
chat.commonMessage(`/${href}`,[]);
}
}}
>
{children}

View File

@ -8,7 +8,7 @@
"Ask DevChat a question or type / for workflow": "向 DevChat 直接提问或输入 '/' 以查看可用的工作流",
"How do I use DevChat?": "如何使用 DevChat",
"balance": "你的账户余额为 {{formatedCurrency}},登录 <4>web.devchat.ai</4> 获得更多 tokens",
"devchat.help": "你想生成一些代码还是对这个项目有疑问?请首先右键单击相关的文件或代码片段,将它们添加到 DevChat 中作为上下文,然后在输入框中写下你的请求或问题,我将基于添加的上下文生成代码或回答你的问题。<br> <br> 你还可以点击输入框左侧的“+”按钮,查看更多添加上下文的快捷方法。此外,在输入框中键入“/”DevChat 会列出可供使用的各类工作流,按 Tab 键或输入完整命令触发你需要的工作流。聊天愉快! <br> <br>下面是一些工作流的示例:<br> <br> [/code: 基于你的提示词和上下文生成代码](#code) <br> <br> [/release_note: 根据加入上下文中的提交历史生成提交说明](#release_note) <br> <br> [/ask-code: 询问任何关于当前代码库的信息,并从这位人工智能代理那里获得答案](#ask_code) <br> <br>你可以点击[设置](#settings)来配置 DevChat",
"devchat.help": "你想生成一些代码还是对这个项目有疑问?请首先右键单击相关的文件或代码片段,将它们添加到 DevChat 中作为上下文,然后在输入框中写下你的请求或问题,我将基于添加的上下文生成代码或回答你的问题。<br> <br> 你还可以点击输入框左侧的“+”按钮,查看更多添加上下文的快捷方法。此外,在输入框中键入“/”DevChat 会列出可供使用的各类工作流,按 Tab 键或输入完整命令触发你需要的工作流。聊天愉快! <br> <br>下面是一些工作流的示例:<br> <br> ",
"devchat.setkey": "你的环境或设置中缺少 DevChat 访问密钥。请输入你的 DevChat 访问密钥,这样我就可以开始正常工作了。<br> <br> <button value=\"get_devchat_key\">注册 DevChat 访问密钥</button> <button value=\"setting_devchat_key\">设置 DevChat 访问密钥</button>",
"devchat.setkey_vscode": "你的环境或设置中缺少 DevChat 访问密钥。请输入你的 DevChat 访问密钥,这样我就可以开始正常工作了。<br> <br> <button value=\"get_devchat_key\" component=\"a\" href=\"https://web.devchat.ai\">注册 DevChat 访问密钥</button> <button value=\"setting_devchat_key\">设置 DevChat 访问密钥</button>",
"Is DevChat Access Key ready?": "DevChat 访问密钥是否已经设置好?",

View File

@ -44,6 +44,9 @@ const chatPanel = observer(() => {
key1: "devchat",
key2: "defaultModel",
});
messageUtil.sendMessage({
command: "getUserAccessKey",
});
};
const getFeatureToggles = () => {
@ -78,18 +81,25 @@ const chatPanel = observer(() => {
}
};
useEffect(() => {
getSettings();
getFeatureToggles();
messageUtil.registerHandler("getUserAccessKey", (message: any) => {
chat.setKey(message.accessKey);
// The history records need to be obtained after setting the key,
// as the display information in the history record requires adjustment
// based on whether the key is present.
chat.fetchHistoryMessages({ pageIndex: 0 }).then();
});
messageUtil.registerHandler("reloadMessage", (message: any) => {
chat.reloadMessage(message);
useEffect(() => {
// Fetch the command menus, before history records are obtained,
// because the display information in the history record requires adjustment
input.fetchCommandMenus().then(()=>{
messageUtil.registerHandler("reloadMessage", (message: any) => {
chat.reloadMessage(message);
});
// The history records need to be obtained after setting the key,
// as the display information in the history record requires adjustment
// based on whether the key is present.
messageUtil.registerHandler("getUserAccessKey", (message: any) => {
chat.setKey(message.accessKey);
chat.fetchHistoryMessages({ pageIndex: 0 }).then();
});
// The history records need to be obtained after setting the key,
input.fetchContextMenus().then();
input.fetchModelMenus().then();
getFeatureToggles();
getSettings();
});
messageUtil.registerHandler(
"receiveMessagePartial",

View File

@ -1,7 +1,8 @@
import { types, flow, Instance } from "mobx-state-tree";
import { types, flow, Instance ,getParent} from "mobx-state-tree";
import messageUtil from "@/util/MessageUtil";
import { ChatContext } from "@/views/stores/InputStore";
import yaml from "js-yaml";
import { RootInstance } from "./RootStore";
interface Context {
content: string;
@ -104,6 +105,17 @@ export const ChatStore = types
self.scrollBottom++;
};
const helpWorkflowCommands = () =>{
const rootStore = getParent<RootInstance>(self);
return rootStore.input.commandMenus.map((item) => {
if(item.name === "help"){
return "";
}
return `<a class="workflow_command" href="${item.pattern}">/${item.name}: ${item.description}</a>`;
}).join("\n\n");
};
const lastNonEmptyHash = () => {
let lastNonEmptyHash;
for (let i = self.messages.length - 1; i >= 0; i--) {
@ -130,6 +142,7 @@ export const ChatStore = types
});
const helpMessage = (originalMessage = false) => {
let helps = `
Do you want to write some code or have a question about the project? Simply right-click on your chosen files or code snippets and add them to DevChat. Feel free to ask me anything or let me help you with coding.
@ -137,17 +150,7 @@ Don't forget to check out the "+" button on the left of the input to add more co
To get started, here are some of the things that I can do for you:
[/code: write code based on your prompt](#code)
[/release_note: draft a release note based on your latest commits](#release_note)
${
self.features["ask-code"]
? "[/ask-code: ask anything about your codebase and get answers from our AI agent](#ask_code)"
: ""
}
You can configure DevChat from [Settings](#settings).`;
${helpWorkflowCommands()}`;
const setKeyMessage = `
Devchat key is missing from your environment or settings. Kindly input your DevChat key, and I'll ensure DevChat is all set for you.
@ -268,6 +271,7 @@ Thinking...
startGenerating,
commonMessage,
userInput,
helpWorkflowCommands,
devchatAsk: flow(function* (userMessage, chatContexts) {
self.messages.push({
type: "user",

View File

@ -33,6 +33,19 @@ const regModelMenus = async () => {
});
};
const regCommandMenus = async () => {
return new Promise<Item[]>((resolve, reject) => {
try {
messageUtil.sendMessage({ command: 'regCommandList' });
messageUtil.registerHandler("regCommandList",(message: { result: Item[] }) => {
resolve(message.result);
});
} catch (e) {
reject(e);
}
});
};
export const ChatContext = types.model({
file: types.maybe(types.string),
path: types.maybe(types.string),
@ -88,11 +101,6 @@ export const InputStore = types
setCurrentMenuIndex(index: number) {
self.currentMenuIndex = index;
},
updateCommands(items) {
self.commandMenus.clear();
self.commandMenus.push(...items);
self.commandMenus.push({ name: 'help', description: 'View the DevChat documentation.', pattern: 'help' });
},
fetchContextMenus: flow(function* () {
try {
const items = yield regContextMenus();
@ -110,18 +118,11 @@ export const InputStore = types
}
}),
fetchCommandMenus: flow(function* () {
const regCommandMenus = async () => {
return new Promise<Item[]>((resolve, reject) => {
try {
messageUtil.sendMessage({ command: 'regCommandList' });
} catch (e) {
reject(e);
}
});
};
try {
yield regCommandMenus();
const items = yield regCommandMenus();
self.commandMenus.clear();
self.commandMenus.push(...items);
self.commandMenus.push({ name: 'help', description: 'View the DevChat documentation.', pattern: 'help' });
} catch (error) {
console.error("Failed to fetch command menus", error);
}