@lobehub/lobehub 2.0.0-next.163 → 2.0.0-next.165
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/desktop-feature-implementation.mdc +31 -34
- package/.cursor/rules/desktop-local-tools-implement.mdc +3 -3
- package/.cursor/rules/desktop-window-management.mdc +56 -66
- package/CHANGELOG.md +52 -0
- package/README.md +6 -6
- package/README.zh-CN.md +6 -6
- package/apps/desktop/Development.md +42 -46
- package/apps/desktop/README.md +37 -1
- package/apps/desktop/README.zh-CN.md +26 -1
- package/apps/desktop/electron.vite.config.ts +1 -0
- package/apps/desktop/src/main/controllers/AuthCtr.ts +4 -3
- package/apps/desktop/src/main/controllers/BrowserWindowsCtr.ts +33 -20
- package/apps/desktop/src/main/controllers/DevtoolsCtr.ts +4 -2
- package/apps/desktop/src/main/controllers/LocalFileCtr.ts +14 -13
- package/apps/desktop/src/main/controllers/MenuCtr.ts +5 -4
- package/apps/desktop/src/main/controllers/NetworkProxyCtr.ts +18 -19
- package/apps/desktop/src/main/controllers/NotificationCtr.ts +4 -3
- package/apps/desktop/src/main/controllers/RemoteServerConfigCtr.ts +5 -4
- package/apps/desktop/src/main/controllers/RemoteServerSyncCtr.ts +3 -2
- package/apps/desktop/src/main/controllers/ShellCommandCtr.ts +5 -4
- package/apps/desktop/src/main/controllers/ShortcutCtr.ts +4 -3
- package/apps/desktop/src/main/controllers/SystemCtr.ts +7 -37
- package/apps/desktop/src/main/controllers/SystemServerCtr.ts +38 -0
- package/apps/desktop/src/main/controllers/TrayMenuCtr.ts +5 -4
- package/apps/desktop/src/main/controllers/UpdaterCtr.ts +6 -5
- package/apps/desktop/src/main/controllers/UploadFileCtr.ts +3 -25
- package/apps/desktop/src/main/controllers/UploadFileServerCtr.ts +33 -0
- package/apps/desktop/src/main/controllers/__tests__/AuthCtr.test.ts +9 -1
- package/apps/desktop/src/main/controllers/__tests__/BrowserWindowsCtr.test.ts +29 -9
- package/apps/desktop/src/main/controllers/__tests__/DevtoolsCtr.test.ts +12 -3
- package/apps/desktop/src/main/controllers/__tests__/LocalFileCtr.test.ts +7 -0
- package/apps/desktop/src/main/controllers/__tests__/MenuCtr.test.ts +10 -0
- package/apps/desktop/src/main/controllers/__tests__/NetworkProxyCtr.test.ts +10 -0
- package/apps/desktop/src/main/controllers/__tests__/NotificationCtr.test.ts +8 -0
- package/apps/desktop/src/main/controllers/__tests__/RemoteServerConfigCtr.test.ts +8 -0
- package/apps/desktop/src/main/controllers/__tests__/RemoteServerSyncCtr.test.ts +1 -0
- package/apps/desktop/src/main/controllers/__tests__/ShellCommandCtr.test.ts +10 -0
- package/apps/desktop/src/main/controllers/__tests__/ShortcutCtr.test.ts +11 -0
- package/apps/desktop/src/main/controllers/__tests__/SystemCtr.test.ts +43 -73
- package/apps/desktop/src/main/controllers/__tests__/SystemServerCtr.test.ts +75 -0
- package/apps/desktop/src/main/controllers/__tests__/TrayMenuCtr.test.ts +24 -13
- package/apps/desktop/src/main/controllers/__tests__/UpdaterCtr.test.ts +13 -2
- package/apps/desktop/src/main/controllers/__tests__/UploadFileCtr.test.ts +29 -108
- package/apps/desktop/src/main/controllers/__tests__/UploadFileServerCtr.test.ts +55 -0
- package/apps/desktop/src/main/controllers/_template.ts +2 -2
- package/apps/desktop/src/main/controllers/index.ts +5 -29
- package/apps/desktop/src/main/controllers/registry.ts +52 -0
- package/apps/desktop/src/main/core/App.ts +15 -47
- package/apps/desktop/src/main/core/__tests__/App.test.ts +5 -4
- package/apps/desktop/src/main/core/infrastructure/IoCContainer.ts +0 -5
- package/apps/desktop/src/main/core/infrastructure/__tests__/IoCContainer.test.ts +0 -50
- package/apps/desktop/src/main/exports.d.ts +8 -0
- package/apps/desktop/src/main/exports.ts +2 -0
- package/apps/desktop/src/main/global.d.ts +3 -0
- package/apps/desktop/src/main/modules/fileSearch/__tests__/macOS.integration.test.ts +17 -8
- package/apps/desktop/src/main/package.json +10 -0
- package/apps/desktop/src/main/services/fileSrv.ts +1 -1
- package/apps/desktop/src/main/utils/ipc/__tests__/base.test.ts +91 -0
- package/apps/desktop/src/main/utils/ipc/base.ts +170 -0
- package/apps/desktop/src/main/utils/ipc/index.ts +11 -0
- package/apps/desktop/src/main/utils/ipc/utility.ts +20 -0
- package/apps/desktop/src/preload/electronApi.ts +4 -1
- package/apps/desktop/src/preload/invoke.test.ts +13 -16
- package/apps/desktop/src/preload/invoke.ts +2 -5
- package/apps/desktop/src/preload/routeInterceptor.test.ts +13 -13
- package/apps/desktop/src/preload/routeInterceptor.ts +4 -4
- package/apps/desktop/tsconfig.json +15 -5
- package/changelog/v1.json +14 -0
- package/locales/ar/auth.json +3 -0
- package/locales/bg-BG/auth.json +3 -0
- package/locales/de-DE/auth.json +3 -0
- package/locales/en-US/auth.json +4 -1
- package/locales/es-ES/auth.json +3 -0
- package/locales/fa-IR/auth.json +3 -0
- package/locales/fr-FR/auth.json +3 -0
- package/locales/it-IT/auth.json +3 -0
- package/locales/ja-JP/auth.json +3 -0
- package/locales/ko-KR/auth.json +3 -0
- package/locales/nl-NL/auth.json +3 -0
- package/locales/pl-PL/auth.json +3 -0
- package/locales/pt-BR/auth.json +3 -0
- package/locales/ru-RU/auth.json +3 -0
- package/locales/tr-TR/auth.json +3 -0
- package/locales/vi-VN/auth.json +3 -0
- package/locales/zh-CN/auth.json +3 -0
- package/locales/zh-TW/auth.json +3 -0
- package/package.json +4 -3
- package/packages/electron-client-ipc/src/index.ts +1 -1
- package/packages/electron-client-ipc/src/ipc.test.ts +62 -0
- package/packages/electron-client-ipc/src/ipc.ts +63 -0
- package/packages/electron-client-ipc/src/streamInvoke.ts +7 -1
- package/packages/electron-client-ipc/src/types/dispatch.ts +1 -10
- package/packages/electron-client-ipc/vitest.config.mts +10 -0
- package/packages/electron-server-ipc/src/ipcClient.ts +1 -2
- package/packages/electron-server-ipc/src/ipcServer.ts +1 -2
- package/packages/electron-server-ipc/src/types/index.ts +1 -5
- package/pnpm-workspace.yaml +1 -1
- package/scripts/i18nWorkflow/const.ts +2 -2
- package/scripts/i18nWorkflow/i18nConfig.ts +7 -0
- package/scripts/i18nWorkflow/utils.ts +1 -1
- package/src/app/[variants]/(auth)/signup/[[...signup]]/BetterAuthSignUpForm.tsx +23 -0
- package/src/app/[variants]/(main)/(mobile)/me/(home)/features/UserBanner.tsx +3 -9
- package/src/app/[variants]/(main)/discover/(detail)/provider/features/Sidebar/ActionButton/ProviderConfig.tsx +2 -2
- package/src/app/[variants]/(main)/profile/(home)/Client.tsx +206 -138
- package/src/features/User/PlanTag.tsx +4 -4
- package/src/locales/default/auth.ts +3 -0
- package/src/locales/default/setting.ts +1 -0
- package/src/server/modules/ElectronIPCClient/index.ts +59 -13
- package/src/services/electron/__tests__/devtools.test.ts +10 -6
- package/src/services/electron/autoUpdate.ts +5 -5
- package/src/services/electron/desktopNotification.ts +4 -7
- package/src/services/electron/devtools.ts +2 -2
- package/src/services/electron/file.ts +3 -2
- package/src/services/electron/localFileService.ts +17 -16
- package/src/services/electron/remoteServer.ts +7 -6
- package/src/services/electron/settings.ts +9 -11
- package/src/services/electron/system.ts +8 -6
- package/src/store/chat/slices/plugin/actions/pluginTypes.ts +1 -1
- package/src/store/global/actions/general.ts +8 -10
- package/src/utils/electron/desktopRemoteRPCFetch.ts +3 -2
- package/src/utils/electron/ipc.ts +12 -0
- package/tsconfig.json +5 -0
- package/apps/desktop/src/main/types/ipcClientEvent.ts +0 -3
- package/packages/electron-client-ipc/src/dispatch.ts +0 -41
package/locales/fa-IR/auth.json
CHANGED
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
},
|
|
55
55
|
"betterAuth": {
|
|
56
56
|
"errors": {
|
|
57
|
+
"confirmPasswordRequired": "لطفاً رمز عبور را تأیید کنید",
|
|
57
58
|
"emailExists": "این ایمیل قبلاً ثبت شده است، لطفاً مستقیماً وارد شوید",
|
|
58
59
|
"emailInvalid": "لطفاً یک آدرس ایمیل معتبر وارد کنید",
|
|
59
60
|
"emailNotRegistered": "این ایمیل هنوز ثبت نشده است",
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
"passwordFormat": "رمز عبور باید شامل حروف و اعداد باشد",
|
|
66
67
|
"passwordMaxLength": "رمز عبور نباید بیش از ۶۴ کاراکتر باشد",
|
|
67
68
|
"passwordMinLength": "رمز عبور باید حداقل ۸ کاراکتر باشد",
|
|
69
|
+
"passwordMismatch": "رمزهای عبور وارد شده یکسان نیستند",
|
|
68
70
|
"passwordRequired": "لطفاً رمز عبور را وارد کنید",
|
|
69
71
|
"usernameNotRegistered": "این نام کاربری هنوز ثبت نشده است",
|
|
70
72
|
"usernameRequired": "لطفاً نام کاربری را وارد کنید"
|
|
@@ -125,6 +127,7 @@
|
|
|
125
127
|
"submit": "ورود"
|
|
126
128
|
},
|
|
127
129
|
"signup": {
|
|
130
|
+
"confirmPasswordPlaceholder": "لطفاً رمز عبور را تأیید کنید",
|
|
128
131
|
"emailPlaceholder": "لطفاً آدرس ایمیل را وارد کنید",
|
|
129
132
|
"error": "ثبتنام ناموفق بود، لطفاً دوباره تلاش کنید",
|
|
130
133
|
"firstNamePlaceholder": "نام",
|
package/locales/fr-FR/auth.json
CHANGED
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
},
|
|
55
55
|
"betterAuth": {
|
|
56
56
|
"errors": {
|
|
57
|
+
"confirmPasswordRequired": "Veuillez confirmer le mot de passe",
|
|
57
58
|
"emailExists": "Cet e-mail est déjà enregistré, veuillez vous connecter directement.",
|
|
58
59
|
"emailInvalid": "Veuillez saisir une adresse e-mail valide",
|
|
59
60
|
"emailNotRegistered": "Cette adresse e-mail n'est pas encore enregistrée",
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
"passwordFormat": "Le mot de passe doit contenir à la fois des lettres et des chiffres",
|
|
66
67
|
"passwordMaxLength": "Le mot de passe ne doit pas dépasser 64 caractères",
|
|
67
68
|
"passwordMinLength": "Le mot de passe doit contenir au moins 8 caractères",
|
|
69
|
+
"passwordMismatch": "Les mots de passe saisis ne correspondent pas",
|
|
68
70
|
"passwordRequired": "Veuillez saisir un mot de passe",
|
|
69
71
|
"usernameNotRegistered": "Ce nom d'utilisateur n'est pas encore enregistré",
|
|
70
72
|
"usernameRequired": "Veuillez saisir un nom d'utilisateur"
|
|
@@ -125,6 +127,7 @@
|
|
|
125
127
|
"submit": "Connexion"
|
|
126
128
|
},
|
|
127
129
|
"signup": {
|
|
130
|
+
"confirmPasswordPlaceholder": "Veuillez confirmer le mot de passe",
|
|
128
131
|
"emailPlaceholder": "Veuillez saisir votre adresse e-mail",
|
|
129
132
|
"error": "Échec de l'inscription, veuillez réessayer",
|
|
130
133
|
"firstNamePlaceholder": "Prénom",
|
package/locales/it-IT/auth.json
CHANGED
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
},
|
|
55
55
|
"betterAuth": {
|
|
56
56
|
"errors": {
|
|
57
|
+
"confirmPasswordRequired": "Conferma la password",
|
|
57
58
|
"emailExists": "Questo indirizzo email è già registrato, effettua direttamente l'accesso",
|
|
58
59
|
"emailInvalid": "Inserisci un indirizzo email valido",
|
|
59
60
|
"emailNotRegistered": "Questo indirizzo email non è registrato",
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
"passwordFormat": "La password deve contenere lettere e numeri",
|
|
66
67
|
"passwordMaxLength": "La password non può superare i 64 caratteri",
|
|
67
68
|
"passwordMinLength": "La password deve contenere almeno 8 caratteri",
|
|
69
|
+
"passwordMismatch": "Le password inserite non corrispondono",
|
|
68
70
|
"passwordRequired": "Inserisci la password",
|
|
69
71
|
"usernameNotRegistered": "Questo nome utente non è ancora registrato",
|
|
70
72
|
"usernameRequired": "Inserisci il nome utente"
|
|
@@ -125,6 +127,7 @@
|
|
|
125
127
|
"submit": "Accedi"
|
|
126
128
|
},
|
|
127
129
|
"signup": {
|
|
130
|
+
"confirmPasswordPlaceholder": "Conferma la password",
|
|
128
131
|
"emailPlaceholder": "Inserisci l'indirizzo email",
|
|
129
132
|
"error": "Registrazione fallita, riprova",
|
|
130
133
|
"firstNamePlaceholder": "Nome",
|
package/locales/ja-JP/auth.json
CHANGED
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
},
|
|
55
55
|
"betterAuth": {
|
|
56
56
|
"errors": {
|
|
57
|
+
"confirmPasswordRequired": "パスワードの確認を入力してください",
|
|
57
58
|
"emailExists": "このメールアドレスは既に登録されています。ログインしてください。",
|
|
58
59
|
"emailInvalid": "有効なメールアドレスを入力してください",
|
|
59
60
|
"emailNotRegistered": "このメールアドレスは未登録です",
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
"passwordFormat": "パスワードは英字と数字を含める必要があります",
|
|
66
67
|
"passwordMaxLength": "パスワードは64文字以内で入力してください",
|
|
67
68
|
"passwordMinLength": "パスワードは8文字以上で入力してください",
|
|
69
|
+
"passwordMismatch": "入力されたパスワードが一致しません",
|
|
68
70
|
"passwordRequired": "パスワードを入力してください",
|
|
69
71
|
"usernameNotRegistered": "このユーザー名は未登録です",
|
|
70
72
|
"usernameRequired": "ユーザー名を入力してください"
|
|
@@ -125,6 +127,7 @@
|
|
|
125
127
|
"submit": "ログイン"
|
|
126
128
|
},
|
|
127
129
|
"signup": {
|
|
130
|
+
"confirmPasswordPlaceholder": "パスワードの確認を入力してください",
|
|
128
131
|
"emailPlaceholder": "メールアドレスを入力してください",
|
|
129
132
|
"error": "登録に失敗しました。もう一度お試しください",
|
|
130
133
|
"firstNamePlaceholder": "名",
|
package/locales/ko-KR/auth.json
CHANGED
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
},
|
|
55
55
|
"betterAuth": {
|
|
56
56
|
"errors": {
|
|
57
|
+
"confirmPasswordRequired": "비밀번호 확인이 필요합니다",
|
|
57
58
|
"emailExists": "이 이메일은 이미 등록되어 있습니다. 바로 로그인해 주세요.",
|
|
58
59
|
"emailInvalid": "유효한 이메일 주소를 입력하세요",
|
|
59
60
|
"emailNotRegistered": "이 이메일은 아직 등록되지 않았습니다",
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
"passwordFormat": "비밀번호는 영문자와 숫자를 모두 포함해야 합니다",
|
|
66
67
|
"passwordMaxLength": "비밀번호는 최대 64자까지 입력할 수 있습니다",
|
|
67
68
|
"passwordMinLength": "비밀번호는 최소 8자 이상이어야 합니다",
|
|
69
|
+
"passwordMismatch": "입력한 비밀번호가 일치하지 않습니다",
|
|
68
70
|
"passwordRequired": "비밀번호를 입력하세요",
|
|
69
71
|
"usernameNotRegistered": "해당 사용자 이름은 등록되어 있지 않습니다",
|
|
70
72
|
"usernameRequired": "사용자 이름을 입력하세요"
|
|
@@ -125,6 +127,7 @@
|
|
|
125
127
|
"submit": "로그인"
|
|
126
128
|
},
|
|
127
129
|
"signup": {
|
|
130
|
+
"confirmPasswordPlaceholder": "비밀번호를 다시 입력해 주세요",
|
|
128
131
|
"emailPlaceholder": "이메일 주소를 입력하세요",
|
|
129
132
|
"error": "회원가입에 실패했습니다. 다시 시도하세요",
|
|
130
133
|
"firstNamePlaceholder": "이름",
|
package/locales/nl-NL/auth.json
CHANGED
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
},
|
|
55
55
|
"betterAuth": {
|
|
56
56
|
"errors": {
|
|
57
|
+
"confirmPasswordRequired": "Bevestig alstublieft uw wachtwoord",
|
|
57
58
|
"emailExists": "Dit e-mailadres is al geregistreerd. Log direct in.",
|
|
58
59
|
"emailInvalid": "Voer een geldig e-mailadres in",
|
|
59
60
|
"emailNotRegistered": "Dit e-mailadres is nog niet geregistreerd",
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
"passwordFormat": "Het wachtwoord moet letters en cijfers bevatten",
|
|
66
67
|
"passwordMaxLength": "Het wachtwoord mag maximaal 64 tekens bevatten",
|
|
67
68
|
"passwordMinLength": "Het wachtwoord moet minimaal 8 tekens bevatten",
|
|
69
|
+
"passwordMismatch": "De ingevoerde wachtwoorden komen niet overeen",
|
|
68
70
|
"passwordRequired": "Voer een wachtwoord in",
|
|
69
71
|
"usernameNotRegistered": "Deze gebruikersnaam is nog niet geregistreerd",
|
|
70
72
|
"usernameRequired": "Voer een gebruikersnaam in"
|
|
@@ -125,6 +127,7 @@
|
|
|
125
127
|
"submit": "Inloggen"
|
|
126
128
|
},
|
|
127
129
|
"signup": {
|
|
130
|
+
"confirmPasswordPlaceholder": "Bevestig alstublieft uw wachtwoord",
|
|
128
131
|
"emailPlaceholder": "Voer je e-mailadres in",
|
|
129
132
|
"error": "Registratie mislukt, probeer het opnieuw",
|
|
130
133
|
"firstNamePlaceholder": "Voornaam",
|
package/locales/pl-PL/auth.json
CHANGED
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
},
|
|
55
55
|
"betterAuth": {
|
|
56
56
|
"errors": {
|
|
57
|
+
"confirmPasswordRequired": "Proszę potwierdzić hasło",
|
|
57
58
|
"emailExists": "Ten adres e-mail jest już zarejestrowany, zaloguj się bezpośrednio.",
|
|
58
59
|
"emailInvalid": "Wprowadź poprawny adres e-mail",
|
|
59
60
|
"emailNotRegistered": "Ten adres e-mail nie jest zarejestrowany",
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
"passwordFormat": "Hasło musi zawierać litery i cyfry",
|
|
66
67
|
"passwordMaxLength": "Hasło nie może przekraczać 64 znaków",
|
|
67
68
|
"passwordMinLength": "Hasło musi mieć co najmniej 8 znaków",
|
|
69
|
+
"passwordMismatch": "Wprowadzone hasła nie są takie same",
|
|
68
70
|
"passwordRequired": "Wprowadź hasło",
|
|
69
71
|
"usernameNotRegistered": "Nazwa użytkownika nie została zarejestrowana",
|
|
70
72
|
"usernameRequired": "Wprowadź nazwę użytkownika"
|
|
@@ -125,6 +127,7 @@
|
|
|
125
127
|
"submit": "Zaloguj się"
|
|
126
128
|
},
|
|
127
129
|
"signup": {
|
|
130
|
+
"confirmPasswordPlaceholder": "Proszę potwierdzić hasło",
|
|
128
131
|
"emailPlaceholder": "Wprowadź adres e-mail",
|
|
129
132
|
"error": "Rejestracja nie powiodła się, spróbuj ponownie",
|
|
130
133
|
"firstNamePlaceholder": "Imię",
|
package/locales/pt-BR/auth.json
CHANGED
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
},
|
|
55
55
|
"betterAuth": {
|
|
56
56
|
"errors": {
|
|
57
|
+
"confirmPasswordRequired": "Por favor, confirme a senha",
|
|
57
58
|
"emailExists": "Este e-mail já está registrado. Por favor, faça login diretamente.",
|
|
58
59
|
"emailInvalid": "Por favor, insira um endereço de e-mail válido",
|
|
59
60
|
"emailNotRegistered": "Este e-mail ainda não está registrado",
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
"passwordFormat": "A senha deve conter letras e números",
|
|
66
67
|
"passwordMaxLength": "A senha não pode ter mais de 64 caracteres",
|
|
67
68
|
"passwordMinLength": "A senha deve ter pelo menos 8 caracteres",
|
|
69
|
+
"passwordMismatch": "As senhas inseridas não coincidem",
|
|
68
70
|
"passwordRequired": "Por favor, insira a senha",
|
|
69
71
|
"usernameNotRegistered": "Este nome de usuário ainda não está registrado",
|
|
70
72
|
"usernameRequired": "Por favor, insira o nome de usuário"
|
|
@@ -125,6 +127,7 @@
|
|
|
125
127
|
"submit": "Entrar"
|
|
126
128
|
},
|
|
127
129
|
"signup": {
|
|
130
|
+
"confirmPasswordPlaceholder": "Por favor, confirme a senha",
|
|
128
131
|
"emailPlaceholder": "Por favor, insira o endereço de e-mail",
|
|
129
132
|
"error": "Falha no cadastro, tente novamente",
|
|
130
133
|
"firstNamePlaceholder": "Nome",
|
package/locales/ru-RU/auth.json
CHANGED
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
},
|
|
55
55
|
"betterAuth": {
|
|
56
56
|
"errors": {
|
|
57
|
+
"confirmPasswordRequired": "Пожалуйста, подтвердите пароль",
|
|
57
58
|
"emailExists": "Этот адрес электронной почты уже зарегистрирован. Пожалуйста, войдите в систему.",
|
|
58
59
|
"emailInvalid": "Пожалуйста, введите действительный адрес электронной почты",
|
|
59
60
|
"emailNotRegistered": "Этот адрес электронной почты не зарегистрирован",
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
"passwordFormat": "Пароль должен содержать как буквы, так и цифры",
|
|
66
67
|
"passwordMaxLength": "Пароль не должен превышать 64 символа",
|
|
67
68
|
"passwordMinLength": "Пароль должен содержать не менее 8 символов",
|
|
69
|
+
"passwordMismatch": "Введённые пароли не совпадают",
|
|
68
70
|
"passwordRequired": "Пожалуйста, введите пароль",
|
|
69
71
|
"usernameNotRegistered": "Это имя пользователя не зарегистрировано",
|
|
70
72
|
"usernameRequired": "Пожалуйста, введите имя пользователя"
|
|
@@ -125,6 +127,7 @@
|
|
|
125
127
|
"submit": "Войти"
|
|
126
128
|
},
|
|
127
129
|
"signup": {
|
|
130
|
+
"confirmPasswordPlaceholder": "Пожалуйста, подтвердите пароль",
|
|
128
131
|
"emailPlaceholder": "Введите адрес электронной почты",
|
|
129
132
|
"error": "Не удалось зарегистрироваться, попробуйте снова",
|
|
130
133
|
"firstNamePlaceholder": "Имя",
|
package/locales/tr-TR/auth.json
CHANGED
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
},
|
|
55
55
|
"betterAuth": {
|
|
56
56
|
"errors": {
|
|
57
|
+
"confirmPasswordRequired": "Lütfen şifreyi onaylayın",
|
|
57
58
|
"emailExists": "Bu e-posta adresi zaten kayıtlı, lütfen doğrudan giriş yapın",
|
|
58
59
|
"emailInvalid": "Lütfen geçerli bir e-posta adresi girin",
|
|
59
60
|
"emailNotRegistered": "Bu e-posta henüz kayıtlı değil",
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
"passwordFormat": "Şifre hem harf hem de rakam içermelidir",
|
|
66
67
|
"passwordMaxLength": "Şifre en fazla 64 karakter olabilir",
|
|
67
68
|
"passwordMinLength": "Şifre en az 8 karakter olmalıdır",
|
|
69
|
+
"passwordMismatch": "Girdiğiniz şifreler eşleşmiyor",
|
|
68
70
|
"passwordRequired": "Lütfen şifrenizi girin",
|
|
69
71
|
"usernameNotRegistered": "Bu kullanıcı adı henüz kayıtlı değil",
|
|
70
72
|
"usernameRequired": "Lütfen kullanıcı adınızı girin"
|
|
@@ -125,6 +127,7 @@
|
|
|
125
127
|
"submit": "Giriş Yap"
|
|
126
128
|
},
|
|
127
129
|
"signup": {
|
|
130
|
+
"confirmPasswordPlaceholder": "Lütfen şifreyi onaylayın",
|
|
128
131
|
"emailPlaceholder": "Lütfen e-posta adresinizi girin",
|
|
129
132
|
"error": "Kayıt başarısız oldu, lütfen tekrar deneyin",
|
|
130
133
|
"firstNamePlaceholder": "Ad",
|
package/locales/vi-VN/auth.json
CHANGED
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
},
|
|
55
55
|
"betterAuth": {
|
|
56
56
|
"errors": {
|
|
57
|
+
"confirmPasswordRequired": "Vui lòng xác nhận mật khẩu",
|
|
57
58
|
"emailExists": "Email này đã được đăng ký, vui lòng đăng nhập trực tiếp",
|
|
58
59
|
"emailInvalid": "Vui lòng nhập địa chỉ email hợp lệ",
|
|
59
60
|
"emailNotRegistered": "Email này chưa được đăng ký",
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
"passwordFormat": "Mật khẩu phải bao gồm cả chữ và số",
|
|
66
67
|
"passwordMaxLength": "Mật khẩu không được vượt quá 64 ký tự",
|
|
67
68
|
"passwordMinLength": "Mật khẩu phải có ít nhất 8 ký tự",
|
|
69
|
+
"passwordMismatch": "Mật khẩu nhập hai lần không khớp",
|
|
68
70
|
"passwordRequired": "Vui lòng nhập mật khẩu",
|
|
69
71
|
"usernameNotRegistered": "Tên người dùng này chưa được đăng ký",
|
|
70
72
|
"usernameRequired": "Vui lòng nhập tên người dùng"
|
|
@@ -125,6 +127,7 @@
|
|
|
125
127
|
"submit": "Đăng nhập"
|
|
126
128
|
},
|
|
127
129
|
"signup": {
|
|
130
|
+
"confirmPasswordPlaceholder": "Vui lòng xác nhận mật khẩu",
|
|
128
131
|
"emailPlaceholder": "Vui lòng nhập địa chỉ email",
|
|
129
132
|
"error": "Đăng ký thất bại, vui lòng thử lại",
|
|
130
133
|
"firstNamePlaceholder": "Tên",
|
package/locales/zh-CN/auth.json
CHANGED
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
},
|
|
55
55
|
"betterAuth": {
|
|
56
56
|
"errors": {
|
|
57
|
+
"confirmPasswordRequired": "请确认密码",
|
|
57
58
|
"emailExists": "该邮箱已注册,请直接登录",
|
|
58
59
|
"emailInvalid": "请输入有效的邮箱地址或用户名",
|
|
59
60
|
"emailNotRegistered": "该邮箱或用户名尚未注册",
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
"passwordFormat": "密码必须同时包含字母和数字",
|
|
66
67
|
"passwordMaxLength": "密码最多不超过 64 个字符",
|
|
67
68
|
"passwordMinLength": "密码至少需要 8 个字符",
|
|
69
|
+
"passwordMismatch": "两次输入的密码不一致",
|
|
68
70
|
"passwordRequired": "请输入密码",
|
|
69
71
|
"usernameNotRegistered": "该用户名尚未注册",
|
|
70
72
|
"usernameRequired": "请输入用户名"
|
|
@@ -125,6 +127,7 @@
|
|
|
125
127
|
"submit": "登录"
|
|
126
128
|
},
|
|
127
129
|
"signup": {
|
|
130
|
+
"confirmPasswordPlaceholder": "请确认密码",
|
|
128
131
|
"emailPlaceholder": "请输入邮箱地址",
|
|
129
132
|
"error": "注册失败,请重试",
|
|
130
133
|
"firstNamePlaceholder": "名字",
|
package/locales/zh-TW/auth.json
CHANGED
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
},
|
|
55
55
|
"betterAuth": {
|
|
56
56
|
"errors": {
|
|
57
|
+
"confirmPasswordRequired": "請確認密碼",
|
|
57
58
|
"emailExists": "該電子郵件已註冊,請直接登入",
|
|
58
59
|
"emailInvalid": "請輸入有效的電子郵件地址",
|
|
59
60
|
"emailNotRegistered": "該電子郵件尚未註冊",
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
"passwordFormat": "密碼必須同時包含字母與數字",
|
|
66
67
|
"passwordMaxLength": "密碼長度不得超過 64 個字元",
|
|
67
68
|
"passwordMinLength": "密碼長度至少需為 8 個字元",
|
|
69
|
+
"passwordMismatch": "兩次輸入的密碼不一致",
|
|
68
70
|
"passwordRequired": "請輸入密碼",
|
|
69
71
|
"usernameNotRegistered": "該使用者名稱尚未註冊",
|
|
70
72
|
"usernameRequired": "請輸入使用者名稱"
|
|
@@ -125,6 +127,7 @@
|
|
|
125
127
|
"submit": "登入"
|
|
126
128
|
},
|
|
127
129
|
"signup": {
|
|
130
|
+
"confirmPasswordPlaceholder": "請確認密碼",
|
|
128
131
|
"emailPlaceholder": "請輸入電子郵件地址",
|
|
129
132
|
"error": "註冊失敗,請重試",
|
|
130
133
|
"firstNamePlaceholder": "名字",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/lobehub",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.165",
|
|
4
4
|
"description": "LobeHub - an open-source,comprehensive AI Agent framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"framework",
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"sideEffects": false,
|
|
28
28
|
"workspaces": [
|
|
29
29
|
"packages/*",
|
|
30
|
-
"e2e"
|
|
30
|
+
"e2e",
|
|
31
|
+
"apps/desktop/src/main"
|
|
31
32
|
],
|
|
32
33
|
"scripts": {
|
|
33
34
|
"prebuild": "tsx scripts/prebuild.mts && npm run lint",
|
|
@@ -169,6 +170,7 @@
|
|
|
169
170
|
"@lobehub/charts": "^2.1.2",
|
|
170
171
|
"@lobehub/chat-plugin-sdk": "^1.32.4",
|
|
171
172
|
"@lobehub/chat-plugins-gateway": "^1.9.0",
|
|
173
|
+
"@lobehub/desktop-ipc-typings": "workspace:*",
|
|
172
174
|
"@lobehub/editor": "^1.23.1",
|
|
173
175
|
"@lobehub/icons": "^2.43.1",
|
|
174
176
|
"@lobehub/market-sdk": "^0.23.2",
|
|
@@ -338,7 +340,6 @@
|
|
|
338
340
|
"@types/crypto-js": "^4.2.2",
|
|
339
341
|
"@types/debug": "^4.1.12",
|
|
340
342
|
"@types/fs-extra": "^11.0.4",
|
|
341
|
-
"@types/ioredis": "^5.0.0",
|
|
342
343
|
"@types/ip": "^1.1.3",
|
|
343
344
|
"@types/json-schema": "^7.0.15",
|
|
344
345
|
"@types/lodash": "^4.17.21",
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
|
|
3
|
+
const restoreWindow = (() => {
|
|
4
|
+
const originalWindow = (globalThis as any).window;
|
|
5
|
+
|
|
6
|
+
return () => {
|
|
7
|
+
if (originalWindow === undefined) {
|
|
8
|
+
Reflect.deleteProperty(globalThis as any, 'window');
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
(globalThis as any).window = originalWindow;
|
|
12
|
+
};
|
|
13
|
+
})();
|
|
14
|
+
|
|
15
|
+
describe('getElectronIpc', () => {
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
vi.resetModules();
|
|
18
|
+
restoreWindow();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
restoreWindow();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('returns null when window is not defined', async () => {
|
|
26
|
+
Reflect.deleteProperty(globalThis as any, 'window');
|
|
27
|
+
const { getElectronIpc } = await import('./ipc');
|
|
28
|
+
|
|
29
|
+
expect(getElectronIpc()).toBeNull();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('returns null when invoke is missing on electronAPI', async () => {
|
|
33
|
+
(globalThis as any).window = { electronAPI: {} };
|
|
34
|
+
const { getElectronIpc } = await import('./ipc');
|
|
35
|
+
|
|
36
|
+
expect(getElectronIpc()).toBeNull();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('creates a cached proxy and forwards payloads to invoke', async () => {
|
|
40
|
+
const invoke = vi.fn();
|
|
41
|
+
(globalThis as any).window = {
|
|
42
|
+
electronAPI: {
|
|
43
|
+
invoke,
|
|
44
|
+
onStreamInvoke: vi.fn(),
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const { getElectronIpc } = await import('./ipc');
|
|
49
|
+
|
|
50
|
+
const ipc = getElectronIpc();
|
|
51
|
+
expect(ipc).not.toBeNull();
|
|
52
|
+
|
|
53
|
+
await (ipc as any).system.updateLocale('en-US');
|
|
54
|
+
expect(invoke).toHaveBeenCalledWith('system.updateLocale', 'en-US');
|
|
55
|
+
|
|
56
|
+
await (ipc as any).windows.closeWindow();
|
|
57
|
+
expect(invoke).toHaveBeenCalledWith('windows.closeWindow');
|
|
58
|
+
|
|
59
|
+
const cached = getElectronIpc();
|
|
60
|
+
expect(cached).toBe(ipc);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-empty-interface */
|
|
2
|
+
import type { DispatchInvoke } from './types/dispatch';
|
|
3
|
+
import type { ProxyTRPCRequestParams } from './types/proxyTRPCRequest';
|
|
4
|
+
|
|
5
|
+
interface StreamerCallbacks {
|
|
6
|
+
onData: (chunk: Uint8Array) => void;
|
|
7
|
+
onEnd: () => void;
|
|
8
|
+
onError: (error: Error) => void;
|
|
9
|
+
onResponse: (response: {
|
|
10
|
+
headers: Record<string, string>;
|
|
11
|
+
status: number;
|
|
12
|
+
statusText: string;
|
|
13
|
+
}) => void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface DesktopIpcServicesMap {}
|
|
17
|
+
export type DesktopIpcServices = DesktopIpcServicesMap;
|
|
18
|
+
export type ElectronDesktopIpc = DesktopIpcServices | null;
|
|
19
|
+
|
|
20
|
+
const createInvokeProxy = <IpcServices>(invoke: DispatchInvoke): IpcServices =>
|
|
21
|
+
new Proxy(
|
|
22
|
+
{},
|
|
23
|
+
{
|
|
24
|
+
get(_target, groupKey) {
|
|
25
|
+
if (typeof groupKey !== 'string') return undefined;
|
|
26
|
+
|
|
27
|
+
return new Proxy(
|
|
28
|
+
{},
|
|
29
|
+
{
|
|
30
|
+
get(_methodTarget, methodKey) {
|
|
31
|
+
if (typeof methodKey !== 'string') return undefined;
|
|
32
|
+
|
|
33
|
+
const channel = `${groupKey}.${methodKey}`;
|
|
34
|
+
return (payload?: unknown) =>
|
|
35
|
+
payload === undefined ? invoke(channel) : invoke(channel, payload);
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
);
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
) as IpcServices;
|
|
42
|
+
|
|
43
|
+
let cachedProxy: DesktopIpcServices | null = null;
|
|
44
|
+
|
|
45
|
+
declare global {
|
|
46
|
+
interface Window {
|
|
47
|
+
electronAPI?: {
|
|
48
|
+
invoke?: DispatchInvoke;
|
|
49
|
+
onStreamInvoke: (params: ProxyTRPCRequestParams, callbacks: StreamerCallbacks) => () => void;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const getElectronIpc = (): DesktopIpcServices | null => {
|
|
55
|
+
if (typeof window === 'undefined') return null;
|
|
56
|
+
if (cachedProxy) return cachedProxy;
|
|
57
|
+
|
|
58
|
+
const invoke = window.electronAPI?.invoke;
|
|
59
|
+
if (!invoke) return null;
|
|
60
|
+
|
|
61
|
+
cachedProxy = createInvokeProxy<DesktopIpcServices>(invoke);
|
|
62
|
+
return cachedProxy;
|
|
63
|
+
};
|
|
@@ -34,7 +34,13 @@ export const streamInvoke = async (input: RequestInfo | URL, init?: RequestInit)
|
|
|
34
34
|
},
|
|
35
35
|
});
|
|
36
36
|
|
|
37
|
-
const
|
|
37
|
+
const electronAPI = window.electronAPI;
|
|
38
|
+
if (!electronAPI || !electronAPI.onStreamInvoke) {
|
|
39
|
+
reject(new Error('[streamInvoke] window.electronAPI.onStreamInvoke is not available'));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const cleanup = electronAPI.onStreamInvoke(params, {
|
|
38
44
|
onData: (chunk) => {
|
|
39
45
|
if (streamController) streamController.enqueue(chunk);
|
|
40
46
|
},
|
|
@@ -1,10 +1 @@
|
|
|
1
|
-
|
|
2
|
-
ClientDispatchEventKey,
|
|
3
|
-
ClientDispatchEvents,
|
|
4
|
-
ClientEventReturnType,
|
|
5
|
-
} from '../events';
|
|
6
|
-
|
|
7
|
-
export type DispatchInvoke = <T extends ClientDispatchEventKey>(
|
|
8
|
-
event: T,
|
|
9
|
-
...data: Parameters<ClientDispatchEvents[T]>
|
|
10
|
-
) => Promise<ClientEventReturnType<T>>;
|
|
1
|
+
export type DispatchInvoke = <T = unknown>(event: string, ...data: any[]) => Promise<T>;
|
|
@@ -5,7 +5,6 @@ import os from 'node:os';
|
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
|
|
7
7
|
import { SOCK_FILE, SOCK_INFO_FILE, WINDOW_PIPE_FILE } from './const';
|
|
8
|
-
import { ServerDispatchEventKey } from './events';
|
|
9
8
|
|
|
10
9
|
const log = debug('electron-server-ipc:client');
|
|
11
10
|
|
|
@@ -178,7 +177,7 @@ export class ElectronIpcClient {
|
|
|
178
177
|
}
|
|
179
178
|
|
|
180
179
|
// Send request to Electron IPC server
|
|
181
|
-
public async sendRequest<T>(method:
|
|
180
|
+
public async sendRequest<T>(method: string, params: any = {}): Promise<T> {
|
|
182
181
|
if (!this.socketPath) {
|
|
183
182
|
console.error('Cannot send request: Electron IPC connection not available');
|
|
184
183
|
throw new Error('Electron IPC connection not available');
|
|
@@ -5,7 +5,6 @@ import os from 'node:os';
|
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
|
|
7
7
|
import { SOCK_FILE, SOCK_INFO_FILE, WINDOW_PIPE_FILE } from './const';
|
|
8
|
-
import { ServerDispatchEventKey } from './events';
|
|
9
8
|
import { ElectronIPCEventHandler } from './types';
|
|
10
9
|
|
|
11
10
|
const log = debug('electron-server-ipc:server');
|
|
@@ -107,7 +106,7 @@ export class ElectronIPCServer {
|
|
|
107
106
|
log('Handling request: %s (ID: %s)', method, id);
|
|
108
107
|
|
|
109
108
|
// Execute corresponding operation based on request method
|
|
110
|
-
const eventHandler = this.eventHandler[method
|
|
109
|
+
const eventHandler = this.eventHandler[method];
|
|
111
110
|
if (!eventHandler) {
|
|
112
111
|
console.error('No handler found for method: %s', method);
|
|
113
112
|
return;
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import net from 'node:net';
|
|
2
2
|
|
|
3
|
-
import { ServerDispatchEventKey } from '../events';
|
|
4
|
-
|
|
5
3
|
export type IPCEventMethod = (
|
|
6
4
|
params: any,
|
|
7
5
|
context: { id: string; method: string; socket: net.Socket },
|
|
8
6
|
) => Promise<any>;
|
|
9
7
|
|
|
10
|
-
export type ElectronIPCEventHandler =
|
|
11
|
-
[key in ServerDispatchEventKey]: IPCEventMethod;
|
|
12
|
-
};
|
|
8
|
+
export type ElectronIPCEventHandler = Record<string, IPCEventMethod>;
|
|
13
9
|
|
|
14
10
|
export * from './file';
|
package/pnpm-workspace.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readdirSync } from 'node:fs';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
|
|
4
|
-
import i18nConfig from '
|
|
4
|
+
import i18nConfig from './i18nConfig';
|
|
5
5
|
|
|
6
6
|
export const root = resolve(__dirname, '../..');
|
|
7
7
|
export const localesDir = resolve(root, i18nConfig.output);
|
|
@@ -15,4 +15,4 @@ export const outputLocaleJsonFilepath = (locale: string, file: string) =>
|
|
|
15
15
|
resolve(localesDir, locale, file);
|
|
16
16
|
export const srcDefaultLocales = resolve(root, srcLocalesDir, 'default');
|
|
17
17
|
|
|
18
|
-
export { default as i18nConfig } from '
|
|
18
|
+
export { default as i18nConfig } from './i18nConfig';
|
|
@@ -3,7 +3,7 @@ import { colors } from 'consola/utils';
|
|
|
3
3
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
4
4
|
import { resolve } from 'node:path';
|
|
5
5
|
import prettier from "@prettier/sync";
|
|
6
|
-
import i18nConfig from '
|
|
6
|
+
import i18nConfig from './i18nConfig';
|
|
7
7
|
|
|
8
8
|
let prettierOptions = prettier.resolveConfig(
|
|
9
9
|
resolve(__dirname, '../../.prettierrc.js')
|