Skip to content

Commit 8009cdc

Browse files
authored
Revert "✨[Request] Abstract Storage SDK"
1 parent 21f9822 commit 8009cdc

File tree

32 files changed

+186
-1348
lines changed

32 files changed

+186
-1348
lines changed

backend/database/attachment_db.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ def get_file_size_from_minio(object_name: str, bucket: Optional[str] = None) ->
165165
"""
166166
Get file size by object name
167167
"""
168-
bucket = bucket or minio_client.storage_config.default_bucket
168+
bucket = bucket or minio_client.default_bucket
169169
return minio_client.get_file_size(object_name, bucket)
170170

171171

@@ -207,7 +207,7 @@ def delete_file(object_name: str, bucket: Optional[str] = None) -> Dict[str, Any
207207
Dict[str, Any]: Delete result, containing success flag and error message (if any)
208208
"""
209209
if not bucket:
210-
bucket = minio_client.storage_config.default_bucket
210+
bucket = minio_client.default_bucket
211211
success, result = minio_client.delete_file(object_name, bucket)
212212

213213
response = {"success": success, "object_name": object_name}

backend/database/client.py

Lines changed: 99 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import logging
2+
import os
23
from contextlib import contextmanager
34
from typing import Any, BinaryIO, Dict, List, Optional, Tuple
45

6+
import boto3
57
import psycopg2
8+
from botocore.client import Config
9+
from botocore.exceptions import ClientError
610
from sqlalchemy import create_engine
711
from sqlalchemy.orm import class_mapper, sessionmaker
812

@@ -19,8 +23,6 @@
1923
POSTGRES_USER,
2024
)
2125
from database.db_models import TableBase
22-
from nexent.storage import create_storage_client_from_config, MinIOStorageConfig
23-
2426

2527
logger = logging.getLogger("database.client")
2628

@@ -71,12 +73,6 @@ def clean_string_values(data: Dict[str, Any]) -> Dict[str, Any]:
7173

7274

7375
class MinioClient:
74-
"""
75-
MinIO client wrapper using storage SDK
76-
77-
This class maintains backward compatibility with the existing MinioClient interface
78-
while using the new storage SDK under the hood.
79-
"""
8076
_instance: Optional['MinioClient'] = None
8177

8278
def __new__(cls):
@@ -85,18 +81,39 @@ def __new__(cls):
8581
return cls._instance
8682

8783
def __init__(self):
88-
# Determine if endpoint uses HTTPS
89-
secure = MINIO_ENDPOINT.startswith('https://') if MINIO_ENDPOINT else True
90-
# Initialize storage client using SDK factory
91-
self.storage_config = MinIOStorageConfig(
92-
endpoint=MINIO_ENDPOINT,
93-
access_key=MINIO_ACCESS_KEY,
94-
secret_key=MINIO_SECRET_KEY,
95-
region=MINIO_REGION,
96-
default_bucket=MINIO_DEFAULT_BUCKET,
97-
secure=secure
84+
self.endpoint = MINIO_ENDPOINT
85+
self.access_key = MINIO_ACCESS_KEY
86+
self.secret_key = MINIO_SECRET_KEY
87+
self.region = MINIO_REGION
88+
self.default_bucket = MINIO_DEFAULT_BUCKET
89+
90+
# Initialize S3 client with proxy settings
91+
self.client = boto3.client(
92+
's3',
93+
endpoint_url=self.endpoint,
94+
aws_access_key_id=self.access_key,
95+
aws_secret_access_key=self.secret_key,
96+
region_name=self.region,
97+
config=Config(
98+
signature_version='s3v4',
99+
proxies={
100+
'http': None,
101+
'https': None
102+
}
103+
)
98104
)
99-
self._storage_client = create_storage_client_from_config(self.storage_config)
105+
106+
# Ensure default bucket exists
107+
self._ensure_bucket_exists(self.default_bucket)
108+
109+
def _ensure_bucket_exists(self, bucket_name: str) -> None:
110+
"""Ensure bucket exists, create if it doesn't"""
111+
try:
112+
self.client.head_bucket(Bucket=bucket_name)
113+
except ClientError:
114+
# Bucket doesn't exist, create it
115+
self.client.create_bucket(Bucket=bucket_name)
116+
logger.info(f"Created bucket: {bucket_name}")
100117

101118
def upload_file(
102119
self,
@@ -115,7 +132,16 @@ def upload_file(
115132
Returns:
116133
Tuple[bool, str]: (Success status, File URL or error message)
117134
"""
118-
return self._storage_client.upload_file(file_path, object_name, bucket)
135+
bucket = bucket or self.default_bucket
136+
if object_name is None:
137+
object_name = os.path.basename(file_path)
138+
139+
try:
140+
self.client.upload_file(file_path, bucket, object_name)
141+
file_url = f"/{bucket}/{object_name}"
142+
return True, file_url
143+
except Exception as e:
144+
return False, str(e)
119145

120146
def upload_fileobj(self, file_obj: BinaryIO, object_name: str, bucket: Optional[str] = None) -> Tuple[bool, str]:
121147
"""
@@ -129,7 +155,13 @@ def upload_fileobj(self, file_obj: BinaryIO, object_name: str, bucket: Optional[
129155
Returns:
130156
Tuple[bool, str]: (Success status, File URL or error message)
131157
"""
132-
return self._storage_client.upload_fileobj(file_obj, object_name, bucket)
158+
bucket = bucket or self.default_bucket
159+
try:
160+
self.client.upload_fileobj(file_obj, bucket, object_name)
161+
file_url = f"/{bucket}/{object_name}"
162+
return True, file_url
163+
except Exception as e:
164+
return False, str(e)
133165

134166
def download_file(self, object_name: str, file_path: str, bucket: Optional[str] = None) -> Tuple[bool, str]:
135167
"""
@@ -143,7 +175,12 @@ def download_file(self, object_name: str, file_path: str, bucket: Optional[str]
143175
Returns:
144176
Tuple[bool, str]: (Success status, Success message or error message)
145177
"""
146-
return self._storage_client.download_file(object_name, file_path, bucket)
178+
bucket = bucket or self.default_bucket
179+
try:
180+
self.client.download_file(bucket, object_name, file_path)
181+
return True, f"File downloaded successfully to {file_path}"
182+
except Exception as e:
183+
return False, str(e)
147184

148185
def get_file_url(self, object_name: str, bucket: Optional[str] = None, expires: int = 3600) -> Tuple[bool, str]:
149186
"""
@@ -157,20 +194,23 @@ def get_file_url(self, object_name: str, bucket: Optional[str] = None, expires:
157194
Returns:
158195
Tuple[bool, str]: (Success status, Presigned URL or error message)
159196
"""
160-
return self._storage_client.get_file_url(object_name, bucket, expires)
197+
bucket = bucket or self.default_bucket
198+
try:
199+
url = self.client.generate_presigned_url('get_object', Params={'Bucket': bucket, 'Key': object_name},
200+
ExpiresIn=expires)
201+
return True, url
202+
except Exception as e:
203+
return False, str(e)
161204

162205
def get_file_size(self, object_name: str, bucket: Optional[str] = None) -> int:
163-
"""
164-
Get file size in bytes
165-
166-
Args:
167-
object_name: Object name
168-
bucket: Bucket name, if not specified use default bucket
169-
170-
Returns:
171-
int: File size in bytes, 0 if file not found or error
172-
"""
173-
return self._storage_client.get_file_size(object_name, bucket)
206+
bucket = bucket or self.default_bucket
207+
try:
208+
response = self.client.head_object(Bucket=bucket, Key=object_name)
209+
return int(response['ContentLength'])
210+
except ClientError as e:
211+
logger.error(
212+
f"Get file size by objectname({object_name}) failed: {e}")
213+
return 0
174214

175215
def list_files(self, prefix: str = "", bucket: Optional[str] = None) -> List[dict]:
176216
"""
@@ -183,7 +223,19 @@ def list_files(self, prefix: str = "", bucket: Optional[str] = None) -> List[dic
183223
Returns:
184224
List[dict]: List of file information
185225
"""
186-
return self._storage_client.list_files(prefix, bucket)
226+
bucket = bucket or self.default_bucket
227+
try:
228+
response = self.client.list_objects_v2(
229+
Bucket=bucket, Prefix=prefix)
230+
files = []
231+
if 'Contents' in response:
232+
for obj in response['Contents']:
233+
files.append(
234+
{'key': obj['Key'], 'size': obj['Size'], 'last_modified': obj['LastModified']})
235+
return files
236+
except Exception as e:
237+
logger.error(f"Error listing files: {str(e)}")
238+
return []
187239

188240
def delete_file(self, object_name: str, bucket: Optional[str] = None) -> Tuple[bool, str]:
189241
"""
@@ -196,7 +248,12 @@ def delete_file(self, object_name: str, bucket: Optional[str] = None) -> Tuple[b
196248
Returns:
197249
Tuple[bool, str]: (Success status, Success message or error message)
198250
"""
199-
return self._storage_client.delete_file(object_name, bucket)
251+
bucket = bucket or self.default_bucket
252+
try:
253+
self.client.delete_object(Bucket=bucket, Key=object_name)
254+
return True, f"File {object_name} deleted successfully"
255+
except Exception as e:
256+
return False, str(e)
200257

201258
def get_file_stream(self, object_name: str, bucket: Optional[str] = None) -> Tuple[bool, Any]:
202259
"""
@@ -209,7 +266,12 @@ def get_file_stream(self, object_name: str, bucket: Optional[str] = None) -> Tup
209266
Returns:
210267
Tuple[bool, Any]: (Success status, File stream object or error message)
211268
"""
212-
return self._storage_client.get_file_stream(object_name, bucket)
269+
bucket = bucket or self.default_bucket
270+
try:
271+
response = self.client.get_object(Bucket=bucket, Key=object_name)
272+
return True, response['Body']
273+
except Exception as e:
274+
return False, str(e)
213275

214276

215277
# Create global database and MinIO client instances

backend/utils/document_vector_utils.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -595,10 +595,8 @@ def summarize_document(document_content: str, filename: str, language: str = LAN
595595
{"role": MESSAGE_ROLE["USER"], "content": user_prompt}
596596
]
597597

598-
# Call LLM, allow more tokens for generation
599-
response = llm(messages, max_tokens=max_words * 2)
600-
if not response or not response.content:
601-
return ""
598+
# Call LLM
599+
response = llm(messages, max_tokens=max_words * 2) # Allow more tokens for generation
602600
return response.content.strip()
603601
else:
604602
# Fallback to placeholder if no model configuration
@@ -677,8 +675,6 @@ def summarize_cluster(document_summaries: List[str], language: str = LANGUAGE["Z
677675

678676
# Call LLM
679677
response = llm(messages, max_tokens=max_words * 2) # Allow more tokens for generation
680-
if not response or not response.content:
681-
return ""
682678
return response.content.strip()
683679
else:
684680
# Fallback to placeholder if no model configuration

doc/docs/zh/opensource-memorial-wall.md

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@
1616
请保持消息的礼貌和尊重,符合我们的行为准则。
1717
-->
1818

19-
::: info lzysleep - 2025-11-7
20-
非常不错的项目,很适合快速上手搭建自己的Agent,赞赞赞!
21-
:::
22-
2319
::: info fishcat - 2025-10-31
2420
很好的项目,希望蒸蒸日上
2521
:::
@@ -304,44 +300,12 @@ Nexent功能如此之强大,给我很多帮助,感谢开发者!厉害
304300

305301
::: info niceman - 2025-10-29
306302
感谢 Nexent 让我踏上了开源之旅!希望能参加ict大赛长长见识。项目不错,给个star~
307-
:::
308303

309304
:::info XxHosxX - 2025-11-5
310305
希望参与ICT大赛以及Nexent平台提升自己的能力:)
311-
:::
312306

313307
::: tip Zwer1 - 2025-11-04
314308
感谢 Nexent 让我踏上了开源之旅!平台开发智能体的能力十分强大,希望能够学习到更多东西!
315309
:::
316310

317-
::: tip Zwer1 - 2025-11-04
318-
想参加ICT创新赛
319-
:::
320-
321-
::: tip Jackie - 2025-11-07
322-
期待能使用Nexent成为智能体开发大佬
323-
:::
324-
325-
::: info xiaochenIpter - 2025-11-08
326-
希望能参加ict大赛可以学习到更多知识,感谢 Nexent 让我踏上了开源之旅!平台开发智能体的能力十分强大,希望能够学习到更多东西!
327-
:::
328-
329-
::: info user - 2025-11-08
330311
"🎉 很高兴加入Nexent社区!作为新贡献者,我期待在代码优化、文档完善或测试反馈中尽一份力。#NexentCommunity 让我们一起构建更棒的项目!🚀"
331-
:::
332-
333-
::: pxqn-xing - 2025-11-08
334-
感谢Nexent让我参与ICT大赛以提升自己的能力
335-
:::
336-
337-
::: QIYAN - 2025-11-09
338-
体验华为AI技术的一天
339-
:::
340-
341-
::: tip qiyan111 - 2025-11-10
342-
想试下华为的智能体
343-
:::
344-
345-
:::info XxHosxX - 2025-11-10
346-
自动创建agent的功能挺创新的,试过其他很多平台基本上都是只能通过一句描述语言优化提示词,很少有可以通过一句描述语言直接生成agent的功能,赞!
347-
:::

frontend/app/[locale]/chat/components/chatHeader.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ export function ChatHeader({ title, onRename }: ChatHeaderProps) {
5050
const inputRef = useRef<HTMLInputElement>(null);
5151
const { t } = useTranslation("common");
5252
const { currentLanguage, handleLanguageChange } = useLanguageSwitch();
53-
const { user, isSpeedMode } = useAuth();
54-
const isAdmin = isSpeedMode || user?.role === USER_ROLES.ADMIN;
53+
const { user } = useAuth();
54+
const isAdmin = user?.role === USER_ROLES.ADMIN;
5555

5656
const goToModelSetup = () => {
5757
router.push(`/${currentLanguage}/setup/models`);

0 commit comments

Comments
 (0)