@lobehub/lobehub 2.0.0-next.142 → 2.0.0-next.144

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.
Files changed (58) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/apps/desktop/package.json +1 -0
  3. package/apps/desktop/src/main/core/ui/__tests__/MenuManager.test.ts +320 -0
  4. package/apps/desktop/src/main/core/ui/__tests__/Tray.test.ts +518 -0
  5. package/apps/desktop/src/main/core/ui/__tests__/TrayManager.test.ts +360 -0
  6. package/apps/desktop/src/main/menus/impls/BaseMenuPlatform.test.ts +49 -0
  7. package/apps/desktop/src/main/menus/impls/linux.test.ts +552 -0
  8. package/apps/desktop/src/main/menus/impls/macOS.test.ts +464 -0
  9. package/apps/desktop/src/main/menus/impls/windows.test.ts +429 -0
  10. package/apps/desktop/src/main/modules/fileSearch/__tests__/macOS.integration.test.ts +2 -2
  11. package/apps/desktop/src/main/services/__tests__/fileSearchSrv.test.ts +402 -0
  12. package/apps/desktop/src/main/utils/__tests__/file-system.test.ts +91 -0
  13. package/apps/desktop/src/main/utils/__tests__/logger.test.ts +229 -0
  14. package/apps/desktop/src/preload/electronApi.test.ts +142 -0
  15. package/apps/desktop/src/preload/invoke.test.ts +145 -0
  16. package/apps/desktop/src/preload/routeInterceptor.test.ts +374 -0
  17. package/apps/desktop/src/preload/streamer.test.ts +365 -0
  18. package/apps/desktop/vitest.config.mts +1 -0
  19. package/changelog/v1.json +18 -0
  20. package/locales/ar/marketAuth.json +13 -0
  21. package/locales/bg-BG/marketAuth.json +13 -0
  22. package/locales/de-DE/marketAuth.json +13 -0
  23. package/locales/en-US/marketAuth.json +13 -0
  24. package/locales/es-ES/marketAuth.json +13 -0
  25. package/locales/fa-IR/marketAuth.json +13 -0
  26. package/locales/fr-FR/marketAuth.json +13 -0
  27. package/locales/it-IT/marketAuth.json +13 -0
  28. package/locales/ja-JP/marketAuth.json +13 -0
  29. package/locales/ko-KR/marketAuth.json +13 -0
  30. package/locales/nl-NL/marketAuth.json +13 -0
  31. package/locales/pl-PL/marketAuth.json +13 -0
  32. package/locales/pt-BR/marketAuth.json +13 -0
  33. package/locales/ru-RU/marketAuth.json +13 -0
  34. package/locales/tr-TR/marketAuth.json +13 -0
  35. package/locales/vi-VN/marketAuth.json +13 -0
  36. package/locales/zh-CN/marketAuth.json +13 -0
  37. package/locales/zh-TW/marketAuth.json +13 -0
  38. package/package.json +1 -1
  39. package/packages/database/migrations/0054_better_auth_two_factor.sql +2 -0
  40. package/packages/database/src/core/migrations.json +1 -1
  41. package/packages/database/src/models/user.ts +27 -5
  42. package/packages/types/src/discover/mcp.ts +2 -1
  43. package/packages/types/src/tool/plugin.ts +2 -1
  44. package/scripts/migrateServerDB/errorHint.js +26 -0
  45. package/scripts/migrateServerDB/index.ts +5 -1
  46. package/src/app/[variants]/(main)/chat/settings/features/SmartAgentActionButton/MarketPublishButton.tsx +0 -2
  47. package/src/app/[variants]/(main)/discover/(detail)/mcp/features/Sidebar/ActionButton/index.tsx +33 -7
  48. package/src/features/PluginStore/McpList/List/Action.tsx +20 -1
  49. package/src/layout/AuthProvider/MarketAuth/MarketAuthConfirmModal.tsx +158 -0
  50. package/src/layout/AuthProvider/MarketAuth/MarketAuthProvider.tsx +130 -14
  51. package/src/libs/mcp/types.ts +8 -0
  52. package/src/locales/default/marketAuth.ts +13 -0
  53. package/src/server/routers/lambda/market/index.ts +85 -2
  54. package/src/server/services/discover/index.ts +45 -4
  55. package/src/services/discover.ts +1 -1
  56. package/src/services/mcp.ts +18 -3
  57. package/src/store/tool/slices/mcpStore/action.test.ts +141 -0
  58. package/src/store/tool/slices/mcpStore/action.ts +153 -11
@@ -0,0 +1,365 @@
1
+ import type { ProxyTRPCRequestParams } from '@lobechat/electron-client-ipc';
2
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
3
+
4
+ // Mock electron module
5
+ const mockIpcRendererOn = vi.fn();
6
+ const mockIpcRendererOnce = vi.fn();
7
+ const mockIpcRendererSend = vi.fn();
8
+ const mockIpcRendererRemoveAllListeners = vi.fn();
9
+
10
+ vi.mock('electron', () => ({
11
+ ipcRenderer: {
12
+ on: mockIpcRendererOn,
13
+ once: mockIpcRendererOnce,
14
+ removeAllListeners: mockIpcRendererRemoveAllListeners,
15
+ send: mockIpcRendererSend,
16
+ },
17
+ }));
18
+
19
+ // Mock uuid
20
+ vi.mock('uuid', () => ({
21
+ v4: vi.fn(() => 'test-request-id-123'),
22
+ }));
23
+
24
+ const { onStreamInvoke } = await import('./streamer');
25
+
26
+ describe('onStreamInvoke', () => {
27
+ beforeEach(() => {
28
+ vi.clearAllMocks();
29
+ });
30
+
31
+ it('should set up stream listeners and send start event', () => {
32
+ const params: ProxyTRPCRequestParams = {
33
+ input: { query: 'test' },
34
+ path: 'test.endpoint',
35
+ type: 'query',
36
+ };
37
+
38
+ const callbacks = {
39
+ onData: vi.fn(),
40
+ onEnd: vi.fn(),
41
+ onError: vi.fn(),
42
+ onResponse: vi.fn(),
43
+ };
44
+
45
+ onStreamInvoke(params, callbacks);
46
+
47
+ // Verify listeners are registered
48
+ expect(mockIpcRendererOn).toHaveBeenCalledWith(
49
+ 'stream:data:test-request-id-123',
50
+ expect.any(Function),
51
+ );
52
+ expect(mockIpcRendererOnce).toHaveBeenCalledWith(
53
+ 'stream:end:test-request-id-123',
54
+ expect.any(Function),
55
+ );
56
+ expect(mockIpcRendererOnce).toHaveBeenCalledWith(
57
+ 'stream:error:test-request-id-123',
58
+ expect.any(Function),
59
+ );
60
+ expect(mockIpcRendererOnce).toHaveBeenCalledWith(
61
+ 'stream:response:test-request-id-123',
62
+ expect.any(Function),
63
+ );
64
+
65
+ // Verify start event is sent
66
+ expect(mockIpcRendererSend).toHaveBeenCalledWith('stream:start', {
67
+ ...params,
68
+ requestId: 'test-request-id-123',
69
+ });
70
+ });
71
+
72
+ it('should invoke onData callback when data is received', () => {
73
+ const callbacks = {
74
+ onData: vi.fn(),
75
+ onEnd: vi.fn(),
76
+ onError: vi.fn(),
77
+ onResponse: vi.fn(),
78
+ };
79
+
80
+ const params: ProxyTRPCRequestParams = {
81
+ input: {},
82
+ path: 'test',
83
+ type: 'query',
84
+ };
85
+
86
+ onStreamInvoke(params, callbacks);
87
+
88
+ // Get the data listener callback
89
+ const dataListener = mockIpcRendererOn.mock.calls.find((call) =>
90
+ call[0].includes('stream:data'),
91
+ )?.[1];
92
+
93
+ // Simulate data event
94
+ const testData = Buffer.from('test data');
95
+ dataListener?.(null, testData);
96
+
97
+ expect(callbacks.onData).toHaveBeenCalledWith(new Uint8Array(testData));
98
+ });
99
+
100
+ it('should invoke onResponse callback when response is received', () => {
101
+ const callbacks = {
102
+ onData: vi.fn(),
103
+ onEnd: vi.fn(),
104
+ onError: vi.fn(),
105
+ onResponse: vi.fn(),
106
+ };
107
+
108
+ const params: ProxyTRPCRequestParams = {
109
+ input: {},
110
+ path: 'test',
111
+ type: 'query',
112
+ };
113
+
114
+ onStreamInvoke(params, callbacks);
115
+
116
+ // Get the response listener callback
117
+ const responseListener = mockIpcRendererOnce.mock.calls.find((call) =>
118
+ call[0].includes('stream:response'),
119
+ )?.[1];
120
+
121
+ // Simulate response event
122
+ const testResponse = {
123
+ headers: { 'content-type': 'application/json' },
124
+ status: 200,
125
+ statusText: 'OK',
126
+ };
127
+ responseListener?.(null, testResponse);
128
+
129
+ expect(callbacks.onResponse).toHaveBeenCalledWith(testResponse);
130
+ });
131
+
132
+ it('should invoke onEnd callback and cleanup when stream ends', () => {
133
+ const callbacks = {
134
+ onData: vi.fn(),
135
+ onEnd: vi.fn(),
136
+ onError: vi.fn(),
137
+ onResponse: vi.fn(),
138
+ };
139
+
140
+ const params: ProxyTRPCRequestParams = {
141
+ input: {},
142
+ path: 'test',
143
+ type: 'query',
144
+ };
145
+
146
+ onStreamInvoke(params, callbacks);
147
+
148
+ // Get the end listener callback
149
+ const endListener = mockIpcRendererOnce.mock.calls.find((call) =>
150
+ call[0].includes('stream:end'),
151
+ )?.[1];
152
+
153
+ // Simulate end event
154
+ endListener?.(null);
155
+
156
+ expect(callbacks.onEnd).toHaveBeenCalled();
157
+
158
+ // Verify cleanup
159
+ expect(mockIpcRendererRemoveAllListeners).toHaveBeenCalledWith(
160
+ 'stream:data:test-request-id-123',
161
+ );
162
+ expect(mockIpcRendererRemoveAllListeners).toHaveBeenCalledWith(
163
+ 'stream:end:test-request-id-123',
164
+ );
165
+ expect(mockIpcRendererRemoveAllListeners).toHaveBeenCalledWith(
166
+ 'stream:error:test-request-id-123',
167
+ );
168
+ expect(mockIpcRendererRemoveAllListeners).toHaveBeenCalledWith(
169
+ 'stream:response:test-request-id-123',
170
+ );
171
+ });
172
+
173
+ it('should invoke onError callback and cleanup when error occurs', () => {
174
+ const callbacks = {
175
+ onData: vi.fn(),
176
+ onEnd: vi.fn(),
177
+ onError: vi.fn(),
178
+ onResponse: vi.fn(),
179
+ };
180
+
181
+ const params: ProxyTRPCRequestParams = {
182
+ input: {},
183
+ path: 'test',
184
+ type: 'query',
185
+ };
186
+
187
+ onStreamInvoke(params, callbacks);
188
+
189
+ // Get the error listener callback
190
+ const errorListener = mockIpcRendererOnce.mock.calls.find((call) =>
191
+ call[0].includes('stream:error'),
192
+ )?.[1];
193
+
194
+ // Simulate error event
195
+ const testError = new Error('Stream processing failed');
196
+ errorListener?.(null, testError);
197
+
198
+ expect(callbacks.onError).toHaveBeenCalledWith(testError);
199
+
200
+ // Verify cleanup
201
+ expect(mockIpcRendererRemoveAllListeners).toHaveBeenCalledWith(
202
+ 'stream:data:test-request-id-123',
203
+ );
204
+ expect(mockIpcRendererRemoveAllListeners).toHaveBeenCalledWith(
205
+ 'stream:end:test-request-id-123',
206
+ );
207
+ expect(mockIpcRendererRemoveAllListeners).toHaveBeenCalledWith(
208
+ 'stream:error:test-request-id-123',
209
+ );
210
+ expect(mockIpcRendererRemoveAllListeners).toHaveBeenCalledWith(
211
+ 'stream:response:test-request-id-123',
212
+ );
213
+ });
214
+
215
+ it('should return cleanup function that removes all listeners', () => {
216
+ const callbacks = {
217
+ onData: vi.fn(),
218
+ onEnd: vi.fn(),
219
+ onError: vi.fn(),
220
+ onResponse: vi.fn(),
221
+ };
222
+
223
+ const params: ProxyTRPCRequestParams = {
224
+ input: {},
225
+ path: 'test',
226
+ type: 'query',
227
+ };
228
+
229
+ const cleanup = onStreamInvoke(params, callbacks);
230
+
231
+ // Call cleanup function
232
+ cleanup();
233
+
234
+ // Verify all listeners are removed
235
+ expect(mockIpcRendererRemoveAllListeners).toHaveBeenCalledWith(
236
+ 'stream:data:test-request-id-123',
237
+ );
238
+ expect(mockIpcRendererRemoveAllListeners).toHaveBeenCalledWith(
239
+ 'stream:end:test-request-id-123',
240
+ );
241
+ expect(mockIpcRendererRemoveAllListeners).toHaveBeenCalledWith(
242
+ 'stream:error:test-request-id-123',
243
+ );
244
+ expect(mockIpcRendererRemoveAllListeners).toHaveBeenCalledWith(
245
+ 'stream:response:test-request-id-123',
246
+ );
247
+ });
248
+
249
+ it('should handle multiple data chunks', () => {
250
+ const callbacks = {
251
+ onData: vi.fn(),
252
+ onEnd: vi.fn(),
253
+ onError: vi.fn(),
254
+ onResponse: vi.fn(),
255
+ };
256
+
257
+ const params: ProxyTRPCRequestParams = {
258
+ input: {},
259
+ path: 'test',
260
+ type: 'query',
261
+ };
262
+
263
+ onStreamInvoke(params, callbacks);
264
+
265
+ const dataListener = mockIpcRendererOn.mock.calls.find((call) =>
266
+ call[0].includes('stream:data'),
267
+ )?.[1];
268
+
269
+ // Simulate multiple data chunks
270
+ const chunk1 = Buffer.from('chunk1');
271
+ const chunk2 = Buffer.from('chunk2');
272
+ const chunk3 = Buffer.from('chunk3');
273
+
274
+ dataListener?.(null, chunk1);
275
+ dataListener?.(null, chunk2);
276
+ dataListener?.(null, chunk3);
277
+
278
+ expect(callbacks.onData).toHaveBeenCalledTimes(3);
279
+ expect(callbacks.onData).toHaveBeenNthCalledWith(1, new Uint8Array(chunk1));
280
+ expect(callbacks.onData).toHaveBeenNthCalledWith(2, new Uint8Array(chunk2));
281
+ expect(callbacks.onData).toHaveBeenNthCalledWith(3, new Uint8Array(chunk3));
282
+ });
283
+
284
+ it('should handle complex request parameters', () => {
285
+ const callbacks = {
286
+ onData: vi.fn(),
287
+ onEnd: vi.fn(),
288
+ onError: vi.fn(),
289
+ onResponse: vi.fn(),
290
+ };
291
+
292
+ const params: ProxyTRPCRequestParams = {
293
+ input: {
294
+ filters: { active: true },
295
+ query: 'complex query',
296
+ sort: { field: 'date', order: 'desc' },
297
+ },
298
+ path: 'complex.nested.endpoint',
299
+ type: 'mutation',
300
+ };
301
+
302
+ onStreamInvoke(params, callbacks);
303
+
304
+ expect(mockIpcRendererSend).toHaveBeenCalledWith('stream:start', {
305
+ ...params,
306
+ requestId: 'test-request-id-123',
307
+ });
308
+ });
309
+
310
+ it('should not invoke callbacks after cleanup', () => {
311
+ const callbacks = {
312
+ onData: vi.fn(),
313
+ onEnd: vi.fn(),
314
+ onError: vi.fn(),
315
+ onResponse: vi.fn(),
316
+ };
317
+
318
+ const params: ProxyTRPCRequestParams = {
319
+ input: {},
320
+ path: 'test',
321
+ type: 'query',
322
+ };
323
+
324
+ const cleanup = onStreamInvoke(params, callbacks);
325
+
326
+ // Cleanup immediately
327
+ cleanup();
328
+
329
+ // Try to trigger callbacks after cleanup (this simulates late events)
330
+ const dataListener = mockIpcRendererOn.mock.calls.find((call) =>
331
+ call[0].includes('stream:data'),
332
+ )?.[1];
333
+
334
+ // Since listeners are removed, this shouldn't do anything
335
+ // The actual behavior depends on electron's implementation
336
+ // But we can verify cleanup was called
337
+ expect(mockIpcRendererRemoveAllListeners).toHaveBeenCalledTimes(4);
338
+ });
339
+
340
+ it('should handle empty buffer data', () => {
341
+ const callbacks = {
342
+ onData: vi.fn(),
343
+ onEnd: vi.fn(),
344
+ onError: vi.fn(),
345
+ onResponse: vi.fn(),
346
+ };
347
+
348
+ const params: ProxyTRPCRequestParams = {
349
+ input: {},
350
+ path: 'test',
351
+ type: 'query',
352
+ };
353
+
354
+ onStreamInvoke(params, callbacks);
355
+
356
+ const dataListener = mockIpcRendererOn.mock.calls.find((call) =>
357
+ call[0].includes('stream:data'),
358
+ )?.[1];
359
+
360
+ const emptyBuffer = Buffer.from('');
361
+ dataListener?.(null, emptyBuffer);
362
+
363
+ expect(callbacks.onData).toHaveBeenCalledWith(new Uint8Array(emptyBuffer));
364
+ });
365
+ });
@@ -5,6 +5,7 @@ export default defineConfig({
5
5
  test: {
6
6
  alias: {
7
7
  '@': resolve(__dirname, './src/main'),
8
+ '~common': resolve(__dirname, './src/common'),
8
9
  },
9
10
  coverage: {
10
11
  all: false,
package/changelog/v1.json CHANGED
@@ -1,4 +1,22 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "fixes": [
5
+ "User email unique migration error."
6
+ ]
7
+ },
8
+ "date": "2025-12-02",
9
+ "version": "2.0.0-next.144"
10
+ },
11
+ {
12
+ "children": {
13
+ "features": [
14
+ "Support market cloud endpoint mcp."
15
+ ]
16
+ },
17
+ "date": "2025-12-02",
18
+ "version": "2.0.0-next.143"
19
+ },
2
20
  {
3
21
  "children": {
4
22
  "fixes": [
@@ -1,4 +1,15 @@
1
1
  {
2
+ "authorize": {
3
+ "cancel": "إلغاء",
4
+ "confirm": "تأكيد التفويض",
5
+ "description": {
6
+ "and": "و",
7
+ "prefix": "بالنقر على تأكيد التفويض، فإنك توافق على",
8
+ "privacy": "سياسة الخصوصية",
9
+ "terms": "شروط الخدمة"
10
+ },
11
+ "title": "تأكيد التفويض"
12
+ },
2
13
  "callback": {
3
14
  "buttons": {
4
15
  "close": "إغلاق النافذة"
@@ -33,8 +44,10 @@
33
44
  "stateMissing": "لم يتم العثور على حالة التفويض، يرجى المحاولة مرة أخرى."
34
45
  },
35
46
  "messages": {
47
+ "authorized": "تم تفويض خدمة LobeHub بنجاح",
36
48
  "loading": "جارٍ بدء عملية التفويض...",
37
49
  "success": {
50
+ "cloudMcpInstall": "تم التفويض بنجاح! يمكنك الآن تثبيت إضافة Cloud MCP.",
38
51
  "submit": "تم التفويض بنجاح! يمكنك الآن نشر المساعد.",
39
52
  "upload": "تم التفويض بنجاح! يمكنك الآن نشر إصدار جديد."
40
53
  }
@@ -1,4 +1,15 @@
1
1
  {
2
+ "authorize": {
3
+ "cancel": "Отказ",
4
+ "confirm": "Разреши използването",
5
+ "description": {
6
+ "and": "и",
7
+ "prefix": "С натискане на „Разреши използването“ се съгласявате с",
8
+ "privacy": "Политиката за поверителност",
9
+ "terms": "Условията за ползване"
10
+ },
11
+ "title": "Потвърждаване на оторизацията"
12
+ },
2
13
  "callback": {
3
14
  "buttons": {
4
15
  "close": "Затвори прозореца"
@@ -33,8 +44,10 @@
33
44
  "stateMissing": "Състоянието на упълномощаване не бе намерено, моля опитайте отново."
34
45
  },
35
46
  "messages": {
47
+ "authorized": "Успешно упълномощаване на услугата LobeHub",
36
48
  "loading": "Стартиране на процеса по упълномощаване...",
37
49
  "success": {
50
+ "cloudMcpInstall": "Успешно разрешение! Вече можете да инсталирате приставката Cloud MCP.",
38
51
  "submit": "Упълномощаването е успешно! Вече можете да публикувате помощник.",
39
52
  "upload": "Упълномощаването е успешно! Вече можете да публикувате нова версия."
40
53
  }
@@ -1,4 +1,15 @@
1
1
  {
2
+ "authorize": {
3
+ "cancel": "Abbrechen",
4
+ "confirm": "Autorisieren",
5
+ "description": {
6
+ "and": "und",
7
+ "prefix": "Mit dem Klick auf „Autorisieren“ stimmen Sie den",
8
+ "privacy": "Datenschutzbestimmungen",
9
+ "terms": "Nutzungsbedingungen"
10
+ },
11
+ "title": "Autorisierung bestätigen"
12
+ },
2
13
  "callback": {
3
14
  "buttons": {
4
15
  "close": "Fenster schließen"
@@ -33,8 +44,10 @@
33
44
  "stateMissing": "Autorisierungsstatus nicht gefunden, bitte erneut versuchen."
34
45
  },
35
46
  "messages": {
47
+ "authorized": "LobeHub-Dienst erfolgreich autorisiert",
36
48
  "loading": "Autorisierungsvorgang wird gestartet...",
37
49
  "success": {
50
+ "cloudMcpInstall": "Autorisierung erfolgreich! Sie können jetzt das Cloud MCP-Plugin installieren.",
38
51
  "submit": "Autorisierung erfolgreich! Du kannst jetzt einen Assistenten veröffentlichen.",
39
52
  "upload": "Autorisierung erfolgreich! Du kannst jetzt eine neue Version veröffentlichen."
40
53
  }
@@ -1,4 +1,15 @@
1
1
  {
2
+ "authorize": {
3
+ "cancel": "Cancel",
4
+ "confirm": "Authorize",
5
+ "description": {
6
+ "and": "and",
7
+ "prefix": "By clicking Authorize, you agree to",
8
+ "privacy": "Privacy Policy",
9
+ "terms": "Terms of Service"
10
+ },
11
+ "title": "Confirm Authorization"
12
+ },
2
13
  "callback": {
3
14
  "buttons": {
4
15
  "close": "Close Window"
@@ -33,8 +44,10 @@
33
44
  "stateMissing": "Authorization state not found. Please try again."
34
45
  },
35
46
  "messages": {
47
+ "authorized": "LobeHub service authorized successfully",
36
48
  "loading": "Starting authorization process...",
37
49
  "success": {
50
+ "cloudMcpInstall": "Authorization successful! You can now install the Cloud MCP plugin.",
38
51
  "submit": "Authorization successful! You can now publish your assistant.",
39
52
  "upload": "Authorization successful! You can now publish a new version."
40
53
  }
@@ -1,4 +1,15 @@
1
1
  {
2
+ "authorize": {
3
+ "cancel": "Cancelar",
4
+ "confirm": "Autorizar uso",
5
+ "description": {
6
+ "and": "y",
7
+ "prefix": "Al hacer clic en autorizar uso, se considera que aceptas",
8
+ "privacy": "la Política de Privacidad",
9
+ "terms": "los Términos de Servicio"
10
+ },
11
+ "title": "Confirmar autorización"
12
+ },
2
13
  "callback": {
3
14
  "buttons": {
4
15
  "close": "Cerrar ventana"
@@ -33,8 +44,10 @@
33
44
  "stateMissing": "No se encontró el estado de autenticación, por favor inténtalo de nuevo."
34
45
  },
35
46
  "messages": {
47
+ "authorized": "Autorización del servicio LobeHub realizada con éxito",
36
48
  "loading": "Iniciando el proceso de autenticación...",
37
49
  "success": {
50
+ "cloudMcpInstall": "¡Autorización exitosa! Ahora puedes instalar el complemento Cloud MCP.",
38
51
  "submit": "¡Autenticación exitosa! Ahora puedes publicar asistentes.",
39
52
  "upload": "¡Autenticación exitosa! Ahora puedes publicar una nueva versión."
40
53
  }
@@ -1,4 +1,15 @@
1
1
  {
2
+ "authorize": {
3
+ "cancel": "لغو",
4
+ "confirm": "تأیید مجوز استفاده",
5
+ "description": {
6
+ "and": "و",
7
+ "prefix": "با کلیک بر روی تأیید مجوز استفاده، شما با",
8
+ "privacy": "سیاست حفظ حریم خصوصی",
9
+ "terms": "شرایط خدمات"
10
+ },
11
+ "title": "تأیید مجوز"
12
+ },
2
13
  "callback": {
3
14
  "buttons": {
4
15
  "close": "بستن پنجره"
@@ -33,8 +44,10 @@
33
44
  "stateMissing": "وضعیت احراز هویت یافت نشد، لطفاً دوباره تلاش کنید."
34
45
  },
35
46
  "messages": {
47
+ "authorized": "دسترسی به سرویس LobeHub با موفقیت تأیید شد",
36
48
  "loading": "در حال آغاز فرآیند احراز هویت...",
37
49
  "success": {
50
+ "cloudMcpInstall": "مجوز با موفقیت صادر شد! اکنون می‌توانید افزونه Cloud MCP را نصب کنید.",
38
51
  "submit": "احراز هویت با موفقیت انجام شد! اکنون می‌توانید دستیار را منتشر کنید.",
39
52
  "upload": "احراز هویت با موفقیت انجام شد! اکنون می‌توانید نسخه جدیدی منتشر کنید."
40
53
  }
@@ -1,4 +1,15 @@
1
1
  {
2
+ "authorize": {
3
+ "cancel": "Annuler",
4
+ "confirm": "Autoriser l'utilisation",
5
+ "description": {
6
+ "and": "et",
7
+ "prefix": "En cliquant sur « Autoriser l'utilisation », vous acceptez",
8
+ "privacy": "la Politique de confidentialité",
9
+ "terms": "les Conditions d'utilisation"
10
+ },
11
+ "title": "Confirmer l'autorisation"
12
+ },
2
13
  "callback": {
3
14
  "buttons": {
4
15
  "close": "Fermer la fenêtre"
@@ -33,8 +44,10 @@
33
44
  "stateMissing": "État d'autorisation introuvable, veuillez réessayer."
34
45
  },
35
46
  "messages": {
47
+ "authorized": "Autorisation du service LobeHub réussie",
36
48
  "loading": "Lancement du processus d'autorisation...",
37
49
  "success": {
50
+ "cloudMcpInstall": "Autorisation réussie ! Vous pouvez maintenant installer le plugin Cloud MCP.",
38
51
  "submit": "Autorisation réussie ! Vous pouvez maintenant publier un assistant.",
39
52
  "upload": "Autorisation réussie ! Vous pouvez maintenant publier une nouvelle version."
40
53
  }
@@ -1,4 +1,15 @@
1
1
  {
2
+ "authorize": {
3
+ "cancel": "Annulla",
4
+ "confirm": "Autorizza l'utilizzo",
5
+ "description": {
6
+ "and": "e",
7
+ "prefix": "Facendo clic su 'Autorizza l'utilizzo' si accetta",
8
+ "privacy": "l'Informativa sulla privacy",
9
+ "terms": "i Termini di servizio"
10
+ },
11
+ "title": "Conferma autorizzazione"
12
+ },
2
13
  "callback": {
3
14
  "buttons": {
4
15
  "close": "Chiudi finestra"
@@ -33,8 +44,10 @@
33
44
  "stateMissing": "Stato di autorizzazione non trovato, riprova."
34
45
  },
35
46
  "messages": {
47
+ "authorized": "Autorizzazione al servizio LobeHub avvenuta con successo",
36
48
  "loading": "Avvio del processo di autorizzazione in corso...",
37
49
  "success": {
50
+ "cloudMcpInstall": "Autorizzazione avvenuta con successo! Ora puoi installare il plugin Cloud MCP.",
38
51
  "submit": "Autorizzazione riuscita! Ora puoi pubblicare l'assistente.",
39
52
  "upload": "Autorizzazione riuscita! Ora puoi pubblicare una nuova versione."
40
53
  }
@@ -1,4 +1,15 @@
1
1
  {
2
+ "authorize": {
3
+ "cancel": "キャンセル",
4
+ "confirm": "使用を許可する",
5
+ "description": {
6
+ "and": "および",
7
+ "prefix": "「使用を許可する」をクリックすると、以下に同意したものとみなされます:",
8
+ "privacy": "プライバシーポリシー",
9
+ "terms": "利用規約"
10
+ },
11
+ "title": "認証の確認"
12
+ },
2
13
  "callback": {
3
14
  "buttons": {
4
15
  "close": "ウィンドウを閉じる"
@@ -33,8 +44,10 @@
33
44
  "stateMissing": "認証状態が見つかりません。もう一度お試しください。"
34
45
  },
35
46
  "messages": {
47
+ "authorized": "LobeHub サービスの認証に成功しました",
36
48
  "loading": "認証プロセスを開始しています...",
37
49
  "success": {
50
+ "cloudMcpInstall": "許可が成功しました!これで Cloud MCP プラグインをインストールできます。",
38
51
  "submit": "認証に成功しました!アシスタントを公開できます。",
39
52
  "upload": "認証に成功しました!新しいバージョンを公開できます。"
40
53
  }
@@ -1,4 +1,15 @@
1
1
  {
2
+ "authorize": {
3
+ "cancel": "취소",
4
+ "confirm": "사용 권한 부여",
5
+ "description": {
6
+ "and": "및",
7
+ "prefix": "사용 권한 부여를 클릭하면 다음에 동의한 것으로 간주됩니다",
8
+ "privacy": "개인정보 처리방침",
9
+ "terms": "서비스 이용약관"
10
+ },
11
+ "title": "권한 확인"
12
+ },
2
13
  "callback": {
3
14
  "buttons": {
4
15
  "close": "창 닫기"
@@ -33,8 +44,10 @@
33
44
  "stateMissing": "인증 상태를 찾을 수 없습니다. 다시 시도해 주세요."
34
45
  },
35
46
  "messages": {
47
+ "authorized": "LobeHub 서비스가 성공적으로 인증되었습니다",
36
48
  "loading": "인증 절차를 시작하는 중입니다...",
37
49
  "success": {
50
+ "cloudMcpInstall": "권한 부여 완료! 이제 Cloud MCP 플러그인을 설치할 수 있습니다.",
38
51
  "submit": "인증 성공! 이제 어시스턴트를 게시할 수 있습니다.",
39
52
  "upload": "인증 성공! 이제 새 버전을 게시할 수 있습니다."
40
53
  }