Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(web): support ai code completion #1877

Merged
merged 1 commit into from
Mar 1, 2024
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
21 changes: 21 additions & 0 deletions web/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"react-icons": "^4.8.0",
"react-image-crop": "^10.1.5",
"react-markdown": "^8.0.7",
"react-monaco-copilot": "^1.0.3",
"react-router-dom": "^6.11.2",
"react-syntax-highlighter": "^15.5.0",
"react-window": "^1.8.10",
Expand Down
5 changes: 3 additions & 2 deletions web/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -239,15 +239,16 @@
"FuncListDisplay": "Function List Display",
"ListDisplay": "List Display",
"EditorLanguageServer": "Editor Language Server",
"isOpenLanguageServer": "Enable or Close Language server (only effective when the app config is above 0.5C 1G)",
"isOpenLanguageServer": "Enable typescript language server (only effective when the spec of the app is above 0.5C 1G)",
"Editor": "Editor",
"FuncList": "Function List",
"EditorMode": "Editor Mode",
"OldLogs": "Old Logs",
"MonitorSetting": "Resource Monitor",
"DatabaseMonitor": "Database monitor",
"RuntimeMonitor": "Runtime monitor",
"ClientSetting": "Client settings"
"ClientSetting": "Client settings",
"AICompletion": "Enable code intelligent completion (need refresh)"
},
"StoragePanel": {
"All": "Total Capacity",
Expand Down
7 changes: 4 additions & 3 deletions web/public/locales/zh-CN/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -239,15 +239,16 @@
"FuncListDisplay": "函数列表显示",
"ListDisplay": "列表显示",
"EditorLanguageServer": "编辑器语言服务",
"isOpenLanguageServer": "是否开启语言服务(仅在应用配置高于 0.5C 1G 时生效)",
"isOpenLanguageServer": "是否开启 TypeScript 语言服务(体验更好的类型提示,仅在应用配置高于 0.5C 1G 时生效)",
"Editor": "编辑器",
"FuncList": "函数列表",
"EditorMode": "使用编辑器模式",
"OldLogs": "旧版日志",
"MonitorSetting": "资源监控",
"DatabaseMonitor": "数据库监控",
"RuntimeMonitor": "运行时监控",
"ClientSetting": "客户端设置"
"ClientSetting": "客户端设置",
"AICompletion": "是否开启代码智能补全(需刷新生效)"
},
"StoragePanel": {
"All": "总容量",
Expand Down Expand Up @@ -757,4 +758,4 @@
"Title": "Laf 新版本已经准备好了!",
"Description": "点击立即更新"
}
}
}
7 changes: 4 additions & 3 deletions web/public/locales/zh/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -239,15 +239,16 @@
"FuncListDisplay": "函数列表显示",
"ListDisplay": "列表显示",
"EditorLanguageServer": "编辑器语言服务",
"isOpenLanguageServer": "是否开启语言服务(仅在应用配置高于 0.5C 1G 时生效)",
"isOpenLanguageServer": "是否开启 TypeScript 语言服务(体验更好的类型提示,仅在应用配置高于 0.5C 1G 时生效)",
"Editor": "编辑器",
"FuncList": "函数列表",
"EditorMode": "使用编辑器模式",
"OldLogs": "旧版日志",
"MonitorSetting": "资源监控",
"DatabaseMonitor": "数据库监控",
"RuntimeMonitor": "运行时监控",
"ClientSetting": "客户端设置"
"ClientSetting": "客户端设置",
"AICompletion": "是否开启代码智能补全(需刷新生效)"
},
"StoragePanel": {
"All": "总容量",
Expand Down Expand Up @@ -757,4 +758,4 @@
"Title": "Laf 新版本已经准备好了!",
"Description": "点击立即更新"
}
}
}
19 changes: 18 additions & 1 deletion web/src/components/Editor/FunctionEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useEffect, useMemo, useRef, useState } from "react";
import { useCompletionFeature } from "react-monaco-copilot";
import * as monaco from "monaco-editor/esm/vs/editor/editor.api";
import {
RegisteredFileSystemProvider,
Expand All @@ -15,7 +16,9 @@ import { createUrl, createWebSocketAndStartClient, performInit } from "./Languag
import { TFunction } from "@/apis/typing";
import useFunctionCache from "@/hooks/useFunctionCache";
import useFunctionStore from "@/pages/app/functions/store";
import useCustomSettingStore from "@/pages/customSetting";
import useGlobalStore from "@/pages/globalStore";
import useSiteSettingStore from "@/pages/siteSetting";

export const fileSystemProvider = new RegisteredFileSystemProvider(false);
registerFileSystemOverlay(1, fileSystemProvider);
Expand All @@ -37,11 +40,14 @@ function FunctionEditor(props: {
}) {
const { onChange, path, className, colorMode = COLOR_MODE.light, fontSize = 14, value } = props;

const editorRef = useRef<monaco.editor.IStandaloneCodeEditor | null>();
const editorRef = useRef<monaco.editor.IStandaloneCodeEditor>();
const subscriptionRef = useRef<monaco.IDisposable | undefined>(undefined);
const monacoEl = useRef(null);
const globalStore = useGlobalStore((state) => state);
const { allFunctionList, setLSPStatus, LSPStatus } = useFunctionStore((state) => state);
const { commonSettings } = useCustomSettingStore();
const { siteSettings } = useSiteSettingStore();

const functionCache = useFunctionCache();
const [functionList, setFunctionList] = useState(allFunctionList);
const baseUrl = globalStore.currentApp.host;
Expand All @@ -53,6 +59,13 @@ function FunctionEditor(props: {
}
}, [baseUrl]);

const aiCompleteUrl = siteSettings.ai_complete_url?.value;
const completionFeature = useCompletionFeature({
monaco: monaco,
editor: editorRef.current,
apiUrl: aiCompleteUrl || "",
});

useEffect(() => {
const startLSP = () => {
const lspWebSocket = createWebSocketAndStartClient(url, globalStore.currentApp.develop_token);
Expand Down Expand Up @@ -152,6 +165,10 @@ function FunctionEditor(props: {
keybinding: monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyP,
command: null,
});

if (commonSettings.useCopilot && aiCompleteUrl) {
completionFeature.onMounted();
}
});
}

Expand Down
25 changes: 20 additions & 5 deletions web/src/components/Editor/TSEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useEffect, useRef } from "react";
import { useCompletionFeature } from "react-monaco-copilot";
import { Spinner } from "@chakra-ui/react";
import { Editor, Monaco } from "@monaco-editor/react";
import * as monaco from "monaco-editor/esm/vs/editor/editor.api";
Expand All @@ -10,6 +11,8 @@ import "./useWorker";

import useFunctionCache from "@/hooks/useFunctionCache";
import useFunctionStore from "@/pages/app/functions/store";
import useCustomSettingStore from "@/pages/customSetting";
import useSiteSettingStore from "@/pages/siteSetting";

const autoImportTypings = new AutoImportTypings();

Expand All @@ -24,14 +27,23 @@ export default function TSEditor(props: {

const functionCache = useFunctionCache();
const { currentFunction, allFunctionList } = useFunctionStore((state) => state);
const { commonSettings } = useCustomSettingStore();
const { siteSettings } = useSiteSettingStore();

const aiCompleteUrl = siteSettings.ai_complete_url?.value;

const monacoRef = useRef<Monaco>();
const editorRef = useRef<monaco.editor.IStandaloneCodeEditor>();
const loadModalsRef = useRef(loadModals);
const loadModelsRef = useRef(loadModels);
const completionFeature = useCompletionFeature({
monaco: monacoRef.current,
editor: editorRef.current,
apiUrl: aiCompleteUrl || "",
});

loadModalsRef.current = loadModals;
loadModelsRef.current = loadModels;

function loadModals(monaco: Monaco) {
function loadModels(monaco: Monaco) {
allFunctionList.forEach((item: any) => {
const uri = monaco.Uri.file(`${RUNTIMES_PATH}/${item.name}.ts`);
if (!monaco.editor.getModel(uri)) {
Expand All @@ -47,15 +59,18 @@ export default function TSEditor(props: {
function handleEditorDidMount(editor: monaco.editor.IStandaloneCodeEditor, monaco: Monaco) {
monacoRef.current = monaco;
editorRef.current = editor;
if (commonSettings.useCopilot && aiCompleteUrl) {
completionFeature.onMounted();
}
setTimeout(() => {
loadModalsRef.current(monacoRef.current!);
loadModelsRef.current(monacoRef.current!);
autoImportTypings.loadDefaults(monacoRef.current);
}, 10);
}

useEffect(() => {
if (monacoRef.current) {
loadModalsRef.current(monacoRef.current!);
loadModelsRef.current(monacoRef.current!);
}
}, [allFunctionList]);

Expand Down
Loading
Loading