Skip to content

Commit 2b883f8

Browse files
authored
Merge branch 'develop' into patch-2
2 parents 5b342b5 + 2bc1dfc commit 2b883f8

File tree

11 files changed

+288
-71
lines changed

11 files changed

+288
-71
lines changed

.github/CODEOWNERS

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
# These owners will be the default owners for everything in the repo
2-
* @Phinease @liutao12138
2+
* @Phinease
3+
4+
doc/docs/zh/opensource-memorial-wall.md @WMC001
5+
doc/docs/en/opensource-memorial-wall.md @WMC001

backend/consts/const.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,4 +265,4 @@
265265
os.getenv("LLM_SLOW_TOKEN_RATE_THRESHOLD", "10.0")) # tokens per second
266266

267267
# APP Version
268-
APP_VERSION = "v1.7.4.1"
268+
APP_VERSION = "v1.7.5.1"

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

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,11 +170,30 @@ Nexent的自然语言生成Agent以及多智能体协同是我一直在研究的
170170
::: info - 2025-10-15
171171
希望能参加ict大赛长长见识,提高水平~
172172
:::
173+
173174
参加ICT大赛来了解 Nexent,这真的是个很好的平台,未来一起前行吧
174175

175176
::: info niceman - 2025-10-27 
176177
希望能参加ict大赛可以学习到更多知识,感谢 Nexent 让我踏上了开源之旅~
177178

178179
::: info violet-dq - 2025-10-28 
179180
想要自己尝试搭建智能体,感叹Nexent的功能如此强大!
180-
:::厉害
181+
:::
182+
183+
::: info yang 2025-11-02
184+
Nexent功能如此之强大,给我很多帮助,感谢开发者!厉害
185+
186+
:::info y-dq - 2025-10-28 
187+
想要自己尝试搭建智能体,感叹Nexent的功能如此强大!
188+
:::
189+
190+
::: Pharaoh-C - 2025-11-2
191+
研究多智能体协作方向,Nexent 的多智能体协同功能让我眼前一亮,这在学术研究中太重要了。我用 Nexent 搭建了一个AI赛博医生,能够自动索引中西医文献、给一些症状做出解答。开源的力量真的很强大,希望更多研究者能加入进来!
192+
:::
193+
194+
::: info xUxIAOrUI -2025-10-28
195+
“零代码生成智能体”的概念非常吸引我.作为在校大学生,这是我第一次接触开源项目。通过初步的了解,发现Nexent是一个很好的平台,之后也会在使用的过程中尝试提出一些有用的意见。期待Nexent越来越好!
196+
:::
197+
198+
::: info niceman - 2025-10-29
199+
希望能参加ict大赛可以学习到更多知识,感谢 Nexent 让我踏上了开源之旅~

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

Lines changed: 102 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import {
99
ChevronLeft,
1010
ChevronRight,
1111
User,
12+
Database,
13+
Box,
14+
Bot,
1215
} from "lucide-react";
1316

1417
import { Button } from "@/components/ui/button";
@@ -37,7 +40,8 @@ import { StaticScrollArea } from "@/components/ui/scrollArea";
3740
import { USER_ROLES } from "@/const/modelConfig";
3841
import { useConfig } from "@/hooks/useConfig";
3942
import { useResponsiveTextSize } from "@/hooks/useResponsiveTextSize";
40-
import { Spin, Tag, ConfigProvider } from "antd";
43+
import { Spin, Tag, ConfigProvider, Dropdown, Menu } from "antd";
44+
import type { MenuProps } from "antd";
4145
import { getRoleColor } from "@/lib/auth";
4246
import { useAuth } from "@/hooks/useAuth";
4347
import { extractColorsFromUri } from "@/lib/avatar";
@@ -120,6 +124,7 @@ export function ChatSidebar({
120124
onRename,
121125
onDelete,
122126
onSettingsClick,
127+
settingsMenuItems,
123128
onDropdownOpenChange,
124129
onToggleSidebar,
125130
expanded,
@@ -237,6 +242,100 @@ export function ChatSidebar({
237242
);
238243
};
239244

245+
// Get icon for menu item based on key
246+
const getMenuIcon = (key: string) => {
247+
switch (key) {
248+
case "models":
249+
return <Box className="h-4 w-4" />;
250+
case "knowledges":
251+
return <Database className="h-4 w-4" />;
252+
case "agents":
253+
return <Bot className="h-4 w-4" />;
254+
}
255+
};
256+
257+
// Render settings button (with dropdown for admin, plain button for regular users)
258+
const renderSettingsButton = (isCollapsed: boolean = false) => {
259+
const buttonContent = (
260+
<Button
261+
variant="ghost"
262+
size="icon"
263+
className={isCollapsed ? "h-10 w-10 rounded-full hover:bg-slate-100" : "size-10 rounded-full hover:bg-slate-100"}
264+
onClick={settingsMenuItems ? undefined : onSettingsClick}
265+
>
266+
<Settings className={isCollapsed ? "h-6 w-6" : "size-5"} />
267+
</Button>
268+
);
269+
270+
// If settingsMenuItems is provided, show dropdown with icons
271+
if (settingsMenuItems && settingsMenuItems.length > 0) {
272+
const menuProps: MenuProps = {
273+
items: settingsMenuItems.map((item, index) => ({
274+
key: item.key,
275+
label: (
276+
<div className="flex items-center gap-3 py-1">
277+
<span className="text-gray-600">{getMenuIcon(item.key)}</span>
278+
<span className="text-sm font-medium">{item.label}</span>
279+
</div>
280+
),
281+
onClick: item.onClick,
282+
style: {
283+
padding: "8px 16px",
284+
},
285+
})),
286+
style: {
287+
minWidth: "240px",
288+
borderRadius: "8px",
289+
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
290+
},
291+
};
292+
293+
return (
294+
<TooltipProvider>
295+
<Tooltip>
296+
<TooltipTrigger asChild>
297+
<ConfigProvider
298+
getPopupContainer={() => document.body}
299+
theme={{
300+
components: {
301+
Dropdown: {
302+
paddingBlock: 4,
303+
},
304+
},
305+
}}
306+
>
307+
<Dropdown menu={menuProps} placement="topRight" trigger={["click"]}>
308+
<div className={isCollapsed ? "flex justify-center" : ""}>
309+
{buttonContent}
310+
</div>
311+
</Dropdown>
312+
</ConfigProvider>
313+
</TooltipTrigger>
314+
<TooltipContent side={isCollapsed ? "right" : "top"}>
315+
{t("chatLeftSidebar.settings")}
316+
</TooltipContent>
317+
</Tooltip>
318+
</TooltipProvider>
319+
);
320+
}
321+
322+
// Otherwise, show plain button for regular users (shouldn't reach here anymore)
323+
return (
324+
<TooltipProvider>
325+
<Tooltip>
326+
<TooltipTrigger asChild>
327+
<div className={isCollapsed ? "flex justify-center" : ""}>
328+
{buttonContent}
329+
</div>
330+
</TooltipTrigger>
331+
<TooltipContent side={isCollapsed ? "right" : "top"}>
332+
{t("chatLeftSidebar.settings")}
333+
</TooltipContent>
334+
</Tooltip>
335+
</TooltipProvider>
336+
);
337+
};
338+
240339
// Render dialog list items
241340
const renderDialogList = (dialogs: ConversationListItem[], title: string) => {
242341
if (dialogs.length === 0) return null;
@@ -461,25 +560,7 @@ export function ChatSidebar({
461560
) : null}
462561

463562
{/* Settings button */}
464-
<TooltipProvider>
465-
<Tooltip>
466-
<TooltipTrigger asChild>
467-
<div className="flex justify-center">
468-
<Button
469-
variant="ghost"
470-
size="icon"
471-
className="h-10 w-10 rounded-full hover:bg-slate-100"
472-
onClick={onSettingsClick}
473-
>
474-
<Settings className="h-6 w-6" />
475-
</Button>
476-
</div>
477-
</TooltipTrigger>
478-
<TooltipContent side="right">
479-
{t("chatLeftSidebar.settings")}
480-
</TooltipContent>
481-
</Tooltip>
482-
</TooltipProvider>
563+
{renderSettingsButton(true)}
483564
</>
484565
);
485566
};
@@ -628,14 +709,7 @@ export function ChatSidebar({
628709
</div>
629710
</ConfigProvider>
630711
) : null}
631-
<Button
632-
variant="ghost"
633-
size="icon"
634-
className="size-10 rounded-full hover:bg-slate-100"
635-
onClick={onSettingsClick}
636-
>
637-
<Settings className="size-5" />
638-
</Button>
712+
{renderSettingsButton(false)}
639713
</div>
640714
</div>
641715
) : (

frontend/app/[locale]/chat/internal/chatInterface.tsx

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,6 +1533,48 @@ export function ChatInterface() {
15331533
};
15341534
}, []);
15351535

1536+
// Handle settings click - not used when menu items are provided
1537+
const handleSettingsClick = () => {
1538+
// This function is kept for compatibility but not used
1539+
// Both admin and regular users now use dropdown menus
1540+
};
1541+
1542+
// Settings menu items based on user role
1543+
const settingsMenuItems = user?.role === "admin" ? [
1544+
// Admin has three options
1545+
{
1546+
key: "models",
1547+
label: t("chatLeftSidebar.settingsMenu.modelConfig"),
1548+
onClick: () => {
1549+
localStorage.setItem("show_page", "1");
1550+
router.push("/setup/models");
1551+
},
1552+
},
1553+
{
1554+
key: "knowledges",
1555+
label: t("chatLeftSidebar.settingsMenu.knowledgeConfig"),
1556+
onClick: () => {
1557+
router.push("/setup/knowledges");
1558+
},
1559+
},
1560+
{
1561+
key: "agents",
1562+
label: t("chatLeftSidebar.settingsMenu.agentConfig"),
1563+
onClick: () => {
1564+
router.push("/setup/agents");
1565+
},
1566+
},
1567+
] : [
1568+
// Regular user only has knowledge base configuration
1569+
{
1570+
key: "knowledges",
1571+
label: t("chatLeftSidebar.settingsMenu.knowledgeConfig"),
1572+
onClick: () => {
1573+
router.push("/setup/knowledges");
1574+
},
1575+
},
1576+
];
1577+
15361578
return (
15371579
<>
15381580
<div className="flex h-screen">
@@ -1546,13 +1588,8 @@ export function ChatInterface() {
15461588
onDialogClick={handleDialogClick}
15471589
onRename={handleConversationRename}
15481590
onDelete={handleConversationDeleteClick}
1549-
onSettingsClick={() => {
1550-
localStorage.setItem(
1551-
"show_page",
1552-
user?.role === "admin" ? "1" : "2"
1553-
);
1554-
router.push("/setup");
1555-
}}
1591+
onSettingsClick={handleSettingsClick}
1592+
settingsMenuItems={settingsMenuItems}
15561593
onDropdownOpenChange={(open: boolean, id: string | null) =>
15571594
setOpenDropdownId(open ? id : null)
15581595
}

0 commit comments

Comments
 (0)