Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@
"**/src/**/route.ts": "${dirname(1)}/${dirname} • route",
"**/src/**/index.tsx": "${dirname} • component",

"**/src/database/repositories/*/index.ts": "${dirname} • db repository",
"**/src/database/models/*.ts": "${filename} • db model",
"**/src/database/schemas/*.ts": "${filename} • db schema",
"**/packages/database/src/repositories/*/index.ts": "${dirname} • db repository",
"**/packages/database/src/models/*.ts": "${filename} • db model",
"**/packages/database/src/schemas/*.ts": "${filename} • db schema",

"**/src/services/*.ts": "${filename} • service",
"**/src/services/*/client.ts": "${dirname} • client service",
Expand All @@ -81,7 +81,7 @@
"**/src/store/*/slices/*/reducer.ts": "${dirname(2)}/${dirname} • reducer",

"**/src/config/modelProviders/*.ts": "${filename} • provider",
"**/packages/model-bank/src/aiModels/aiModels/*.ts": "${filename} • model",
"**/packages/model-bank/src/aiModels/*.ts": "${filename} • model",
"**/packages/model-runtime/src/*/index.ts": "${dirname} • runtime",

"**/src/server/services/*/index.ts": "${dirname} • server/service",
Expand Down
50 changes: 50 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,56 @@

# Changelog

### [Version 1.120.6](https://github.com/lobehub/lobe-chat/compare/v1.120.5...v1.120.6)

<sup>Released on **2025-09-01**</sup>

#### 💄 Styles

- **misc**: Add upload hint for non-visual model.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### Styles

- **misc**: Add upload hint for non-visual model, closes [#7969](https://github.com/lobehub/lobe-chat/issues/7969) ([1224f4e](https://github.com/lobehub/lobe-chat/commit/1224f4e))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>

### [Version 1.120.5](https://github.com/lobehub/lobe-chat/compare/v1.120.4...v1.120.5)

<sup>Released on **2025-09-01**</sup>

#### 🐛 Bug Fixes

- **ai-image**: Save config.imageUrl with fullUrl instead of key.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### What's fixed

- **ai-image**: Save config.imageUrl with fullUrl instead of key, closes [#9016](https://github.com/lobehub/lobe-chat/issues/9016) ([bad009a](https://github.com/lobehub/lobe-chat/commit/bad009a))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>

### [Version 1.120.4](https://github.com/lobehub/lobe-chat/compare/v1.120.3...v1.120.4)

<sup>Released on **2025-09-01**</sup>
Expand Down
12 changes: 12 additions & 0 deletions changelog/v1.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
[
{
"children": {
"improvements": ["Add upload hint for non-visual model."]
},
"date": "2025-09-01",
"version": "1.120.6"
},
{
"children": {},
"date": "2025-09-01",
"version": "1.120.5"
},
{
"children": {
"improvements": ["Adjust ControlsForm component to adapt to mobile phone display."]
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@lobehub/chat",
"version": "1.120.4",
"version": "1.120.6",
"description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
"keywords": [
"framework",
Expand Down
4 changes: 2 additions & 2 deletions packages/model-bank/src/standard-parameters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ export const DEFAULT_DIMENSION_CONSTRAINTS = {
} as const;

export const CHAT_MODEL_IMAGE_GENERATION_PARAMS: ModelParamsSchema = {
imageUrl: {
default: null,
imageUrls: {
default: [],
},
prompt: { default: '' },
};
Expand Down
111 changes: 111 additions & 0 deletions src/components/DragUpload/useDragUpload.test.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,43 @@
import { act, renderHook } from '@testing-library/react';
import { App } from 'antd';
import { Mock, afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

import { useModelSupportVision } from '@/hooks/useModelSupportVision';
import { useAgentStore } from '@/store/agent';
import { agentSelectors } from '@/store/agent/slices/chat';

import { getContainer, useDragUpload } from './useDragUpload';

// Mock the hooks and components
vi.mock('@/hooks/useModelSupportVision');
vi.mock('@/store/agent');
vi.mock('antd', () => ({
App: {
useApp: () => ({
message: {
warning: vi.fn(),
},
}),
},
}));

describe('useDragUpload', () => {
let mockOnUploadFiles: Mock;
let mockMessage: { warning: Mock };

beforeEach(() => {
mockOnUploadFiles = vi.fn();
mockMessage = { warning: vi.fn() };
vi.useFakeTimers();
document.body.innerHTML = '';

// Mock the hooks
(useModelSupportVision as Mock).mockReturnValue(false);
(useAgentStore as unknown as Mock).mockImplementation((selector) => {
if (selector === agentSelectors.currentAgentModel) return 'test-model';
if (selector === agentSelectors.currentAgentModelProvider) return 'test-provider';
return null;
});
});

afterEach(() => {
Expand Down Expand Up @@ -115,6 +143,89 @@ describe('useDragUpload', () => {

expect(mockOnUploadFiles).toHaveBeenCalledWith([mockFile]);
});

it('should show warning when dropping image file with vision not supported', async () => {
renderHook(() => useDragUpload(mockOnUploadFiles));

const mockImageFile = new File([''], 'test.png', { type: 'image/png' });
const dropEvent = new Event('drop') as DragEvent;
Object.defineProperty(dropEvent, 'dataTransfer', {
value: {
items: [
{
kind: 'file',
getAsFile: () => mockImageFile,
webkitGetAsEntry: () => ({
isFile: true,
file: (cb: (file: File) => void) => cb(mockImageFile),
}),
},
],
types: ['Files'],
},
});

await act(async () => {
window.dispatchEvent(dropEvent);
});

expect(mockOnUploadFiles).not.toHaveBeenCalled();
});

it('should show warning when pasting image file with vision not supported', async () => {
renderHook(() => useDragUpload(mockOnUploadFiles));

const mockImageFile = new File([''], 'test.png', { type: 'image/png' });
const pasteEvent = new Event('paste') as ClipboardEvent;
Object.defineProperty(pasteEvent, 'clipboardData', {
value: {
items: [
{
kind: 'file',
getAsFile: () => mockImageFile,
webkitGetAsEntry: () => null,
},
],
},
});

await act(async () => {
window.dispatchEvent(pasteEvent);
});

expect(mockOnUploadFiles).not.toHaveBeenCalled();
});

it('should allow image files when vision is supported', async () => {
(useModelSupportVision as Mock).mockReturnValue(true);

renderHook(() => useDragUpload(mockOnUploadFiles));

const mockImageFile = new File([''], 'test.png', { type: 'image/png' });
const dropEvent = new Event('drop') as DragEvent;
Object.defineProperty(dropEvent, 'dataTransfer', {
value: {
items: [
{
kind: 'file',
getAsFile: () => mockImageFile,
webkitGetAsEntry: () => ({
isFile: true,
file: (cb: (file: File) => void) => cb(mockImageFile),
}),
},
],
types: ['Files'],
},
});

await act(async () => {
window.dispatchEvent(dropEvent);
});

expect(mockOnUploadFiles).toHaveBeenCalledWith([mockImageFile]);
expect(App.useApp().message.warning).not.toHaveBeenCalled();
});
});

describe('getContainer', () => {
Expand Down
26 changes: 26 additions & 0 deletions src/components/DragUpload/useDragUpload.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
/* eslint-disable no-undef */
import { App } from 'antd';
import { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';

import { useModelSupportVision } from '@/hooks/useModelSupportVision';
import { useAgentStore } from '@/store/agent';
import { agentSelectors } from '@/store/agent/selectors';

const DRAGGING_ROOT_ID = 'dragging-root';
export const getContainer = () => document.querySelector(`#${DRAGGING_ROOT_ID}`);
Expand Down Expand Up @@ -62,12 +68,18 @@ const getFileListFromDataTransferItems = async (items: DataTransferItem[]) => {
};

export const useDragUpload = (onUploadFiles: (files: File[]) => Promise<void>) => {
const { t } = useTranslation('chat');
const { message } = App.useApp();
const [isDragging, setIsDragging] = useState(false);
// When a file is dragged to a different area, the 'dragleave' event may be triggered,
// causing isDragging to be mistakenly set to false.
// to fix this issue, use a counter to ensure the status change only when drag event left the browser window .
const dragCounter = useRef(0);

const model = useAgentStore(agentSelectors.currentAgentModel);
const provider = useAgentStore(agentSelectors.currentAgentModelProvider);
const supportVision = useModelSupportVision(model, provider);

const handleDragEnter = (e: DragEvent) => {
if (!e.dataTransfer?.items || e.dataTransfer.items.length === 0) return;

Expand Down Expand Up @@ -113,6 +125,13 @@ export const useDragUpload = (onUploadFiles: (files: File[]) => Promise<void>) =

if (files.length === 0) return;

// 检查是否有图片文件且模型不支持视觉功能
const hasImageFiles = files.some((file) => file.type.startsWith('image/'));
if (hasImageFiles && !supportVision) {
message.warning(t('upload.clientMode.visionNotSupported'));
return;
}

// upload files
onUploadFiles(files);
};
Expand All @@ -125,6 +144,13 @@ export const useDragUpload = (onUploadFiles: (files: File[]) => Promise<void>) =
const files = await getFileListFromDataTransferItems(items);
if (files.length === 0) return;

// 检查是否有图片文件且模型不支持视觉功能
const hasImageFiles = files.some((file) => file.type.startsWith('image/'));
if (hasImageFiles && !supportVision) {
message.warning(t('upload.clientMode.visionNotSupported'));
return;
}

onUploadFiles(files);
};

Expand Down
1 change: 1 addition & 0 deletions src/locales/default/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ export default {
actionFiletip: '上传文件',
actionTooltip: '上传',
disabled: '当前模型不支持视觉识别和文件分析,请切换模型后使用',
visionNotSupported: '当前模型不支持视觉识别,请切换模型后使用',
},
preview: {
prepareTasks: '准备分块...',
Expand Down
Loading
Loading