@lobehub/lobehub 2.0.0-next.141 → 2.0.0-next.143

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 (75) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/Dockerfile +2 -0
  3. package/apps/desktop/package.json +1 -0
  4. package/apps/desktop/src/main/controllers/__tests__/McpInstallCtr.test.ts +286 -0
  5. package/apps/desktop/src/main/controllers/__tests__/NotificationCtr.test.ts +347 -0
  6. package/apps/desktop/src/main/controllers/__tests__/RemoteServerConfigCtr.test.ts +645 -0
  7. package/apps/desktop/src/main/controllers/__tests__/RemoteServerSyncCtr.test.ts +372 -0
  8. package/apps/desktop/src/main/controllers/__tests__/SystemCtr.test.ts +276 -0
  9. package/apps/desktop/src/main/controllers/__tests__/UploadFileCtr.test.ts +171 -0
  10. package/apps/desktop/src/main/core/browser/__tests__/Browser.test.ts +573 -0
  11. package/apps/desktop/src/main/core/browser/__tests__/BrowserManager.test.ts +415 -0
  12. package/apps/desktop/src/main/core/infrastructure/__tests__/I18nManager.test.ts +353 -0
  13. package/apps/desktop/src/main/core/infrastructure/__tests__/IoCContainer.test.ts +156 -0
  14. package/apps/desktop/src/main/core/infrastructure/__tests__/ProtocolManager.test.ts +348 -0
  15. package/apps/desktop/src/main/core/infrastructure/__tests__/StaticFileServerManager.test.ts +481 -0
  16. package/apps/desktop/src/main/core/infrastructure/__tests__/StoreManager.test.ts +164 -0
  17. package/apps/desktop/src/main/core/infrastructure/__tests__/UpdaterManager.test.ts +513 -0
  18. package/apps/desktop/src/main/core/ui/__tests__/MenuManager.test.ts +320 -0
  19. package/apps/desktop/src/main/core/ui/__tests__/Tray.test.ts +518 -0
  20. package/apps/desktop/src/main/core/ui/__tests__/TrayManager.test.ts +360 -0
  21. package/apps/desktop/src/main/menus/impls/BaseMenuPlatform.test.ts +49 -0
  22. package/apps/desktop/src/main/menus/impls/linux.test.ts +552 -0
  23. package/apps/desktop/src/main/menus/impls/macOS.test.ts +464 -0
  24. package/apps/desktop/src/main/menus/impls/windows.test.ts +429 -0
  25. package/apps/desktop/src/main/modules/fileSearch/__tests__/macOS.integration.test.ts +2 -2
  26. package/apps/desktop/src/main/services/__tests__/fileSearchSrv.test.ts +402 -0
  27. package/apps/desktop/src/main/utils/__tests__/file-system.test.ts +91 -0
  28. package/apps/desktop/src/main/utils/__tests__/logger.test.ts +229 -0
  29. package/apps/desktop/src/preload/electronApi.test.ts +142 -0
  30. package/apps/desktop/src/preload/invoke.test.ts +145 -0
  31. package/apps/desktop/src/preload/routeInterceptor.test.ts +374 -0
  32. package/apps/desktop/src/preload/streamer.test.ts +365 -0
  33. package/apps/desktop/vitest.config.mts +1 -0
  34. package/changelog/v1.json +18 -0
  35. package/docs/self-hosting/environment-variables/model-provider.mdx +31 -0
  36. package/docs/self-hosting/environment-variables/model-provider.zh-CN.mdx +30 -0
  37. package/locales/ar/marketAuth.json +13 -0
  38. package/locales/bg-BG/marketAuth.json +13 -0
  39. package/locales/de-DE/marketAuth.json +13 -0
  40. package/locales/en-US/marketAuth.json +13 -0
  41. package/locales/es-ES/marketAuth.json +13 -0
  42. package/locales/fa-IR/marketAuth.json +13 -0
  43. package/locales/fr-FR/marketAuth.json +13 -0
  44. package/locales/it-IT/marketAuth.json +13 -0
  45. package/locales/ja-JP/marketAuth.json +13 -0
  46. package/locales/ko-KR/marketAuth.json +13 -0
  47. package/locales/nl-NL/marketAuth.json +13 -0
  48. package/locales/pl-PL/marketAuth.json +13 -0
  49. package/locales/pt-BR/marketAuth.json +13 -0
  50. package/locales/ru-RU/marketAuth.json +13 -0
  51. package/locales/tr-TR/marketAuth.json +13 -0
  52. package/locales/vi-VN/marketAuth.json +13 -0
  53. package/locales/zh-CN/marketAuth.json +13 -0
  54. package/locales/zh-TW/marketAuth.json +13 -0
  55. package/package.json +1 -1
  56. package/packages/database/src/models/user.ts +2 -0
  57. package/packages/model-runtime/src/core/openaiCompatibleFactory/index.ts +6 -3
  58. package/packages/types/src/discover/mcp.ts +2 -1
  59. package/packages/types/src/tool/plugin.ts +2 -1
  60. package/src/app/[variants]/(main)/chat/settings/features/SmartAgentActionButton/MarketPublishButton.tsx +0 -2
  61. package/src/app/[variants]/(main)/discover/(detail)/mcp/features/Sidebar/ActionButton/index.tsx +33 -7
  62. package/src/config/modelProviders/vertexai.ts +1 -1
  63. package/src/envs/llm.ts +4 -0
  64. package/src/features/PluginStore/McpList/List/Action.tsx +20 -1
  65. package/src/layout/AuthProvider/MarketAuth/MarketAuthConfirmModal.tsx +158 -0
  66. package/src/layout/AuthProvider/MarketAuth/MarketAuthProvider.tsx +130 -14
  67. package/src/libs/mcp/types.ts +8 -0
  68. package/src/locales/default/marketAuth.ts +13 -0
  69. package/src/server/modules/ModelRuntime/index.ts +4 -4
  70. package/src/server/routers/lambda/market/index.ts +85 -2
  71. package/src/server/services/discover/index.ts +45 -4
  72. package/src/services/discover.ts +1 -1
  73. package/src/services/mcp.ts +18 -3
  74. package/src/store/tool/slices/mcpStore/action.test.ts +141 -0
  75. 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
+ "features": [
5
+ "Support market cloud endpoint mcp."
6
+ ]
7
+ },
8
+ "date": "2025-12-02",
9
+ "version": "2.0.0-next.143"
10
+ },
11
+ {
12
+ "children": {
13
+ "fixes": [
14
+ "Remove internal apiMode param from chat completion API requests."
15
+ ]
16
+ },
17
+ "date": "2025-12-01",
18
+ "version": "2.0.0-next.142"
19
+ },
2
20
  {
3
21
  "children": {
4
22
  "fixes": [
@@ -121,6 +121,37 @@ If you need to use Azure OpenAI to provide model services, you can refer to the
121
121
  - Default: `-`
122
122
  - Example: `-all,+gemini-1.5-flash-latest,+gemini-1.5-pro-latest`
123
123
 
124
+ ## Vertex AI
125
+
126
+ ### `VERTEXAI_CREDENTIALS`
127
+
128
+ - Type: Required
129
+ - Description: A JSON string of your Google Cloud service account key, you can get the key from [here](/docs/usage/providers/vertexai).
130
+ - Default: -
131
+ - Example: `{"type": "service_account", "project_id": "your-gcp-project-id", ...}`
132
+
133
+ ### `VERTEXAI_PROJECT`
134
+
135
+ - Type: Optional
136
+ - Description: Your Google Cloud project ID. If not set, it will be obtained from the `project_id` field in `VERTEXAI_CREDENTIALS`.
137
+ - Default: -
138
+ - Example: `your-gcp-project-id`
139
+
140
+ ### `VERTEXAI_LOCATION`
141
+
142
+ - Type: Optional
143
+ - Description: The region where your Vertex AI model is located.
144
+ - Default: `global`
145
+ - Example: `us-central1`
146
+
147
+
148
+ ### `VERTEXAI_MODEL_LIST`
149
+
150
+ - Type: Optional
151
+ - Description: Used to control the model list, use `+` to add a model, use `-` to hide a model, use `model_name=display_name` to customize the display name of a model, separated by commas. Definition syntax rules see [model-list][model-list]
152
+ - Default: `-`
153
+ - Example: `-all,+gemini-1.5-flash-latest,+gemini-1.5-pro-latest`
154
+
124
155
  ## Anthropic AI
125
156
 
126
157
  ### `ANTHROPIC_API_KEY`
@@ -119,6 +119,36 @@ LobeChat 在部署时提供了丰富的模型服务商相关的环境变量,
119
119
  - 默认值:`-`
120
120
  - 示例:`-all,+gemini-1.5-flash-latest,+gemini-1.5-pro-latest`
121
121
 
122
+ ## Vertex AI
123
+
124
+ ### `VERTEXAI_CREDENTIALS`
125
+
126
+ - 类型:必选
127
+ - 描述:Google Cloud 服务账号密钥的 JSON 字符串。用于认证和授权访问 Vertex AI 服务,获取方法请参考 [这里](/zh/docs/usage/providers/vertexai)
128
+ - 默认值:-
129
+ - 示例:`{"type": "service_account", "project_id": "your-gcp-project-id", ...}`
130
+
131
+ ### `VERTEXAI_PROJECT`
132
+
133
+ - 类型:可选
134
+ - 描述:你的 Google Cloud 项目 ID。如果未设置,将从 `VERTEXAI_CREDENTIALS` 中的 `project_id` 字段获取。
135
+ - 默认值:-
136
+ - 示例:`your-gcp-project-id`
137
+
138
+ ### `VERTEXAI_LOCATION`
139
+
140
+ - 类型:可选
141
+ - 描述:你的 Vertex AI 模型所在的区域。
142
+ - 默认值:`global`
143
+ - 示例:`us-central1`
144
+
145
+ ### `VERTEXAI_MODEL_LIST`
146
+
147
+ - 类型:可选
148
+ - 描述:用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名<扩展配置>` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则见 [模型列表][model-list]
149
+ - 默认值:`-`
150
+ - 示例:`-all,+gemini-1.5-flash-latest,+gemini-1.5-pro-latest`
151
+
122
152
  ## Anthropic AI
123
153
 
124
154
  ### `ANTHROPIC_API_KEY`
@@ -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
  }