@lobehub/lobehub 2.0.0-next.220 → 2.0.0-next.221

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/.i18nrc.js CHANGED
@@ -1,4 +1,6 @@
1
1
  const { defineConfig } = require('@lobehub/i18n-cli');
2
+ const fs = require('fs');
3
+ const path = require('path');
2
4
 
3
5
  module.exports = defineConfig({
4
6
  entry: 'locales/en-US',
@@ -31,8 +33,8 @@ module.exports = defineConfig({
31
33
  },
32
34
  markdown: {
33
35
  reference:
34
- '你需要保持 mdx 的组件格式,输出文本不需要在最外层包裹任何代码块语法。以下是一些词汇的固定翻译:\n' +
35
- JSON.stringify(require('./glossary.json'), null, 2),
36
+ '你需要保持 mdx 的组件格式,输出文本不需要在最外层包裹任何代码块语法。\n' +
37
+ fs.readFileSync(path.join(__dirname, 'docs/glossary.md'), 'utf-8'),
36
38
  entry: ['./README.zh-CN.md', './contributing/**/*.zh-CN.md', './docs/**/*.zh-CN.mdx'],
37
39
  entryLocale: 'zh-CN',
38
40
  outputLocales: ['en-US'],
package/CHANGELOG.md CHANGED
@@ -2,6 +2,39 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## [Version 2.0.0-next.221](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.220...v2.0.0-next.221)
6
+
7
+ <sup>Released on **2026-01-05**</sup>
8
+
9
+ #### ♻ Code Refactoring
10
+
11
+ - **misc**: Convert glossary from JSON to Markdown table format.
12
+
13
+ #### 🐛 Bug Fixes
14
+
15
+ - **misc**: Resolve desktop upload CORS issue.
16
+
17
+ <br/>
18
+
19
+ <details>
20
+ <summary><kbd>Improvements and Fixes</kbd></summary>
21
+
22
+ #### Code refactoring
23
+
24
+ - **misc**: Convert glossary from JSON to Markdown table format, closes [#11237](https://github.com/lobehub/lobe-chat/issues/11237) ([46a58a8](https://github.com/lobehub/lobe-chat/commit/46a58a8))
25
+
26
+ #### What's fixed
27
+
28
+ - **misc**: Resolve desktop upload CORS issue, closes [#11255](https://github.com/lobehub/lobe-chat/issues/11255) ([49ec5ed](https://github.com/lobehub/lobe-chat/commit/49ec5ed))
29
+
30
+ </details>
31
+
32
+ <div align="right">
33
+
34
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
35
+
36
+ </div>
37
+
5
38
  ## [Version 2.0.0-next.220](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.219...v2.0.0-next.220)
6
39
 
7
40
  <sup>Released on **2026-01-05**</sup>
@@ -374,14 +374,10 @@ export default class Browser {
374
374
  | undefined;
375
375
  logger.info(`Creating new BrowserWindow instance: ${this.identifier}`);
376
376
  logger.debug(`[${this.identifier}] Options for new window: ${JSON.stringify(this.options)}`);
377
- logger.debug(
378
- `[${this.identifier}] Saved window state: ${JSON.stringify(savedState)}`,
379
- );
377
+ logger.debug(`[${this.identifier}] Saved window state: ${JSON.stringify(savedState)}`);
380
378
 
381
379
  const resolvedState = this.resolveWindowState(savedState, { height, width });
382
- logger.debug(
383
- `[${this.identifier}] Resolved window state: ${JSON.stringify(resolvedState)}`,
384
- );
380
+ logger.debug(`[${this.identifier}] Resolved window state: ${JSON.stringify(resolvedState)}`);
385
381
 
386
382
  const browserWindow = new BrowserWindow({
387
383
  ...res,
@@ -569,33 +565,65 @@ export default class Browser {
569
565
  }
570
566
 
571
567
  /**
572
- * Setup CORS bypass for local file server (127.0.0.1:*)
573
- * This is needed for Electron to access files from the local static file server
568
+ * Setup CORS bypass for ALL requests
569
+ * In production, the renderer uses app://next protocol which triggers CORS for all external requests
570
+ * This completely bypasses CORS by:
571
+ * 1. Removing Origin header from requests (prevents OPTIONS preflight)
572
+ * 2. Adding proper CORS response headers using the stored origin value
574
573
  */
575
574
  private setupCORSBypass(browserWindow: BrowserWindow): void {
576
- logger.debug(`[${this.identifier}] Setting up CORS bypass for local file server`);
575
+ logger.debug(`[${this.identifier}] Setting up CORS bypass for all requests`);
577
576
 
578
577
  const session = browserWindow.webContents.session;
579
578
 
580
- // Intercept response headers to add CORS headers
579
+ // Store origin values for each request ID
580
+ const originMap = new Map<number, string>();
581
+
582
+ // Remove Origin header and store it for later use
583
+ session.webRequest.onBeforeSendHeaders((details, callback) => {
584
+ const requestHeaders = { ...details.requestHeaders };
585
+
586
+ // Store and remove Origin header to prevent CORS preflight
587
+ if (requestHeaders['Origin']) {
588
+ originMap.set(details.id, requestHeaders['Origin']);
589
+ delete requestHeaders['Origin'];
590
+ logger.debug(
591
+ `[${this.identifier}] Removed Origin header for: ${details.url} (stored: ${requestHeaders['Origin']})`,
592
+ );
593
+ }
594
+
595
+ callback({ requestHeaders });
596
+ });
597
+
598
+ // Add CORS headers to ALL responses using stored origin
581
599
  session.webRequest.onHeadersReceived((details, callback) => {
582
- const url = details.url;
600
+ const responseHeaders = details.responseHeaders || {};
601
+
602
+ // Get the original origin from our map, fallback to default
603
+ const origin = originMap.get(details.id) || '*';
583
604
 
584
- // Only modify headers for local file server requests (127.0.0.1)
585
- if (url.includes('127.0.0.1') || url.includes('lobe-desktop-file')) {
586
- const responseHeaders = details.responseHeaders || {};
605
+ // Cannot use '*' when Access-Control-Allow-Credentials is true
606
+ responseHeaders['Access-Control-Allow-Origin'] = [origin];
607
+ responseHeaders['Access-Control-Allow-Methods'] = ['GET, POST, PUT, DELETE, OPTIONS, PATCH'];
608
+ responseHeaders['Access-Control-Allow-Headers'] = ['*'];
609
+ responseHeaders['Access-Control-Allow-Credentials'] = ['true'];
587
610
 
588
- // Add CORS headers
589
- responseHeaders['Access-Control-Allow-Origin'] = ['*'];
590
- responseHeaders['Access-Control-Allow-Methods'] = ['GET, POST, PUT, DELETE, OPTIONS'];
591
- responseHeaders['Access-Control-Allow-Headers'] = ['*'];
611
+ // Clean up the stored origin after response
612
+ originMap.delete(details.id);
613
+
614
+ // For OPTIONS requests, add preflight cache and override status
615
+ if (details.method === 'OPTIONS') {
616
+ responseHeaders['Access-Control-Max-Age'] = ['86400']; // 24 hours
617
+ logger.debug(`[${this.identifier}] Adding CORS headers to OPTIONS response`);
592
618
 
593
619
  callback({
594
620
  responseHeaders,
621
+ statusLine: 'HTTP/1.1 200 OK',
595
622
  });
596
- } else {
597
- callback({ responseHeaders: details.responseHeaders });
623
+ return;
598
624
  }
625
+
626
+ callback({ responseHeaders });
599
627
  });
600
628
 
601
629
  logger.debug(`[${this.identifier}] CORS bypass setup completed`);
@@ -36,6 +36,7 @@ const { mockBrowserWindow, mockNativeTheme, mockIpcMain, mockScreen, MockBrowser
36
36
  send: vi.fn(),
37
37
  session: {
38
38
  webRequest: {
39
+ onBeforeSendHeaders: vi.fn(),
39
40
  onHeadersReceived: vi.fn(),
40
41
  },
41
42
  },
package/changelog/v1.json CHANGED
@@ -1,4 +1,16 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "improvements": [
5
+ "Convert glossary from JSON to Markdown table format."
6
+ ],
7
+ "fixes": [
8
+ "Resolve desktop upload CORS issue."
9
+ ]
10
+ },
11
+ "date": "2026-01-05",
12
+ "version": "2.0.0-next.221"
13
+ },
2
14
  {
3
15
  "children": {
4
16
  "fixes": [
@@ -0,0 +1,11 @@
1
+ # Glossary
2
+
3
+ 以下是一些词汇的固定翻译:
4
+
5
+ | develop key | zh-CN(中文) | en-US(English) |
6
+ |-------------| ----------- | -------------- |
7
+ | agent | 助理 | Agent |
8
+ | agentGroup | 群组 | Group |
9
+ | page | 文稿 | Page |
10
+ | topic | 话题 | Topic |
11
+ | thread | 子话题 | Thread |
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "actions.addNewTopic": "开启新话题",
3
3
  "actions.autoRename": "智能重命名",
4
- "actions.confirmRemoveAll": "您即将删除所有主题,此操作无法撤销。",
5
- "actions.confirmRemoveTopic": "您即将删除此主题,此操作无法撤销。",
6
- "actions.confirmRemoveUnstarred": "您即将删除未加星标的主题,此操作无法撤销。",
4
+ "actions.confirmRemoveAll": "您即将删除所有话题,此操作无法撤销。",
5
+ "actions.confirmRemoveTopic": "您即将删除此话题,此操作无法撤销。",
6
+ "actions.confirmRemoveUnstarred": "您即将删除未加星标的话题,此操作无法撤销。",
7
7
  "actions.duplicate": "复制",
8
- "actions.export": "导出主题",
8
+ "actions.export": "导出话题",
9
9
  "actions.import": "导入对话",
10
10
  "actions.openInNewWindow": "打开独立窗口",
11
11
  "actions.removeAll": "删除全部话题",
@@ -24,7 +24,7 @@
24
24
  "groupTitle.byTime.week": "本周",
25
25
  "groupTitle.byTime.yesterday": "昨天",
26
26
  "guide.desc": "点击发送左侧按钮可将当前会话保存为历史话题,并开启新一轮会话",
27
- "guide.title": "主题列表",
27
+ "guide.title": "话题列表",
28
28
  "importError": "导入遇到了问题",
29
29
  "importInvalidFormat": "文件格式不正确。请确认这是有效的 JSON 文件",
30
30
  "importLoading": "正在导入对话…",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/lobehub",
3
- "version": "2.0.0-next.220",
3
+ "version": "2.0.0-next.221",
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",
@@ -24,6 +24,8 @@ export const notebookRouter = router({
24
24
  content: z.string(),
25
25
  description: z.string(),
26
26
  metadata: z.record(z.string(), z.any()).optional(),
27
+ source: z.string().optional().default('notebook'),
28
+ sourceType: z.enum(['file', 'web', 'api', 'topic']).optional().default('api'),
27
29
  title: z.string(),
28
30
  topicId: z.string(),
29
31
  type: z
@@ -39,8 +41,8 @@ export const notebookRouter = router({
39
41
  description: input.description,
40
42
  fileType: input.type,
41
43
  metadata: input.metadata,
42
- source: 'notebook',
43
- sourceType: 'api',
44
+ source: input.source,
45
+ sourceType: input.sourceType,
44
46
  title: input.title,
45
47
  totalCharCount: input.content.length,
46
48
  totalLineCount: input.content.split('\n').length,
@@ -8,6 +8,8 @@ interface CreateDocumentParams {
8
8
  content: string;
9
9
  description: string;
10
10
  metadata?: Record<string, any>;
11
+ source?: string;
12
+ sourceType?: 'file' | 'web' | 'api' | 'topic';
11
13
  title: string;
12
14
  topicId: string;
13
15
  type?: ExtendedDocumentType;
@@ -130,6 +130,8 @@ class WebBrowsingExecutor extends BaseExecutor<typeof WebBrowsingApiName> {
130
130
  const document = await notebookService.createDocument({
131
131
  content: pageData.content,
132
132
  description: pageData.description || `Crawled from ${pageData.url}`,
133
+ source: pageData.url,
134
+ sourceType: 'web',
133
135
  title: pageData.title || pageData.url,
134
136
  topicId: ctx.topicId!,
135
137
  type: 'article',
package/glossary.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "助理": {
3
- "en-US": "Agent"
4
- },
5
- "文稿": {
6
- "en-US": "Page"
7
- }
8
- }