Skip to content

Commit 582eb2a

Browse files
authored
Merge branch 'develop' into patch-1
2 parents b2f4770 + edce9d8 commit 582eb2a

File tree

7 files changed

+116
-34
lines changed

7 files changed

+116
-34
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

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

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

175176
::: info niceman - 2025-10-27 
@@ -180,3 +181,11 @@ Nexent的自然语言生成Agent以及多智能体协同是我一直在研究的
180181

181182
::: info yang 2025-11-02
182183
Nexent功能如此之强大,给我很多帮助,感谢开发者!
184+
185+
:::info y-dq - 2025-10-28 
186+
想要自己尝试搭建智能体,感叹Nexent的功能如此强大!
187+
:::
188+
189+
::: Pharaoh-C - 2025-11-2
190+
研究多智能体协作方向,Nexent 的多智能体协同功能让我眼前一亮,这在学术研究中太重要了。我用 Nexent 搭建了一个AI赛博医生,能够自动索引中西医文献、给一些症状做出解答。开源的力量真的很强大,希望更多研究者能加入进来!
191+
:::

frontend/app/[locale]/setup/agents/components/AgentSetupOrchestrator.tsx

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,27 @@ export default function AgentSetupOrchestrator({
214214
useEffect(() => {
215215
if (isCreatingNewAgent) {
216216
if (!isEditingAgent) {
217-
// Only clear and get new Agent configuration in creating mode
217+
// Clear configuration in creating mode
218218
setBusinessLogic("");
219-
fetchSubAgentIdAndEnableToolList(t);
219+
// Create agent record immediately to get agent ID for generating prompts and using tools
220+
// Only create if we don't already have a mainAgentId
221+
if (!mainAgentId) {
222+
const createAgentRecord = async () => {
223+
try {
224+
const createResult = await getCreatingSubAgentId();
225+
if (createResult.success && createResult.data) {
226+
const newAgentId = createResult.data.agentId;
227+
setMainAgentId(newAgentId);
228+
log.info("Created agent record with ID:", newAgentId);
229+
} else {
230+
log.error("Failed to create agent record:", createResult.message);
231+
}
232+
} catch (error) {
233+
log.error("Error creating agent record:", error);
234+
}
235+
};
236+
createAgentRecord();
237+
}
220238
} else {
221239
// In edit mode, data is loaded in handleEditAgent, here validate the form
222240
}
@@ -236,7 +254,7 @@ export default function AgentSetupOrchestrator({
236254
// Sign that has been initialized
237255
hasInitialized.current = true;
238256
}
239-
}, [isCreatingNewAgent, isEditingAgent]);
257+
}, [isCreatingNewAgent, isEditingAgent, mainAgentId]);
240258

241259
// Listen for changes in the tool status, update the selected tool
242260
useEffect(() => {
@@ -355,6 +373,16 @@ export default function AgentSetupOrchestrator({
355373

356374
// Reset the status when the user cancels the creation of an Agent
357375
const handleCancelCreating = async () => {
376+
// If we created an agent record during creation mode, delete it
377+
if (mainAgentId && isCreatingNewAgent && !isEditingAgent) {
378+
try {
379+
await deleteAgent(Number(mainAgentId));
380+
log.info("Deleted unsaved agent record with ID:", mainAgentId);
381+
} catch (error) {
382+
log.error("Error deleting unsaved agent record:", error);
383+
}
384+
}
385+
358386
// First notify external editing state change to avoid UI jumping
359387
onEditingStateChange?.(false, null);
360388

@@ -368,6 +396,9 @@ export default function AgentSetupOrchestrator({
368396
}
369397
setIsEditingAgent(false);
370398
setEditingAgent(null);
399+
400+
// Clear the mainAgentId
401+
setMainAgentId(null);
371402

372403
// Note: Content clearing is handled by onExitCreation above
373404
// Delay clearing tool and collaborative agent selection to avoid jumping
@@ -424,11 +455,12 @@ export default function AgentSetupOrchestrator({
424455
max_step: number,
425456
business_description: string
426457
) => {
427-
if (name.trim() && mainAgentId) {
458+
if (name.trim()) {
428459
try {
429460
let result;
430461

431462
if (isEditingAgent && editingAgent) {
463+
// Editing existing agent
432464
result = await updateAgent(
433465
Number(editingAgent.id),
434466
name,
@@ -447,6 +479,13 @@ export default function AgentSetupOrchestrator({
447479
businessLogicModelId ?? undefined
448480
);
449481
} else {
482+
// Creating new agent - the agent record should already exist (created when entering create mode)
483+
if (!mainAgentId) {
484+
message.error(t("businessLogic.config.error.noAgentId"));
485+
return;
486+
}
487+
488+
// Update the agent with all the details
450489
result = await updateAgent(
451490
Number(mainAgentId),
452491
name,
@@ -480,6 +519,7 @@ export default function AgentSetupOrchestrator({
480519
setIsCreatingNewAgent(false);
481520
setIsEditingAgent(false);
482521
setEditingAgent(null);
522+
setMainAgentId(null); // Clear mainAgentId after successful save
483523
onEditingStateChange?.(false, null);
484524

485525
setBusinessLogic("");
@@ -690,16 +730,17 @@ export default function AgentSetupOrchestrator({
690730
const targetAgentId =
691731
isEditingAgent && editingAgent ? editingAgent.id : mainAgentId;
692732

693-
if (!targetAgentId) {
694-
message.error(t("businessLogic.config.error.noAgentId"));
695-
return;
696-
}
697-
698733
const newValue = value ?? 5;
699734

700735
// Update local state first
701736
setMainAgentMaxStep(newValue);
702737

738+
// If no agent ID yet (e.g., during initial creation setup), just update local state
739+
// The max steps will be saved when the agent is fully created
740+
if (!targetAgentId) {
741+
return;
742+
}
743+
703744
// Call updateAgent API to save the max steps change
704745
try {
705746
const result = await updateAgent(

frontend/app/[locale]/setup/agents/components/PromptManager.tsx

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -541,26 +541,32 @@ export default function PromptManager({
541541
{t("businessLogic.title")}
542542
</h3>
543543
</div>
544-
<div className="relative">
545-
<Input.TextArea
546-
value={businessLogic}
547-
onChange={(e) => onBusinessLogicChange?.(e.target.value)}
548-
placeholder={t("businessLogic.placeholder")}
549-
className="w-full resize-none p-3 text-sm transition-all duration-300 system-prompt-business-logic"
550-
style={{
551-
minHeight: "120px",
552-
maxHeight: "200px",
553-
paddingRight: "12px",
554-
paddingBottom: "40px", // Reserve space for button
555-
}}
556-
autoSize={{
557-
minRows: 3,
558-
maxRows: 5,
559-
}}
560-
disabled={!isEditingMode}
561-
/>
562-
{/* Generate button */}
563-
<div className="absolute bottom-2 right-2">
544+
545+
{/* 重新设计的容器:分为文本区域和控件区域 */}
546+
<div className="border border-gray-200 rounded-lg overflow-hidden bg-white shadow-sm" style={{ minHeight: "120px", maxHeight: "200px" }}>
547+
{/* 文本内容区域 */}
548+
<div className="px-2 pt-2 pb-1 overflow-hidden" style={{ minHeight: "80px", maxHeight: "160px" }}>
549+
<Input.TextArea
550+
value={businessLogic}
551+
onChange={(e) => onBusinessLogicChange?.(e.target.value)}
552+
placeholder={t("businessLogic.placeholder")}
553+
className="w-full resize-none text-sm transition-all duration-300"
554+
style={{
555+
minHeight: "80px",
556+
maxHeight: "160px",
557+
border: "none",
558+
boxShadow: "none",
559+
padding: 0,
560+
background: "transparent",
561+
overflow: "auto",
562+
}}
563+
autoSize={false}
564+
disabled={!isEditingMode}
565+
/>
566+
</div>
567+
568+
{/* 控件区域 - 固定40px高度,无背景无边框,控件靠右 */}
569+
<div className="h-10 flex items-center justify-end px-3">
564570
<div className="flex items-center gap-2">
565571
<span className="text-xs text-gray-600">{t("businessLogic.config.model")}</span>
566572
<Select

frontend/app/[locale]/setup/models/components/model/ModelAddDialog.tsx

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,26 @@ export const ModelAddDialog = ({ isOpen, onClose, onSuccess }: ModelAddDialogPro
3232
const { t } = useTranslation()
3333
const { message } = App.useApp()
3434
const { updateModelConfig } = useConfig()
35+
36+
// Parse backend error message and return i18n key with params
37+
const parseModelError = (errorMessage: string): { key: string; params?: Record<string, string> } => {
38+
if (!errorMessage) {
39+
return { key: 'model.dialog.error.addFailed' }
40+
}
41+
42+
// Check for name conflict error
43+
const nameConflictMatch = errorMessage.match(/Name ['"]?([^'"]+)['"]? is already in use/i)
44+
if (nameConflictMatch) {
45+
return {
46+
key: 'model.dialog.error.nameConflict',
47+
params: { name: nameConflictMatch[1] }
48+
}
49+
}
50+
51+
// For other errors, return generic error key without showing backend details
52+
return { key: 'model.dialog.error.addFailed' }
53+
}
54+
3555
const [form, setForm] = useState({
3656
type: MODEL_TYPES.LLM as ModelType,
3757
name: "",
@@ -211,7 +231,8 @@ export const ModelAddDialog = ({ isOpen, onClose, onSuccess }: ModelAddDialogPro
211231
onSuccess()
212232
}
213233
} catch (error: any) {
214-
message.error(error?.message || '添加模型失败');
234+
const errorInfo = parseModelError(error?.message || '')
235+
message.error(t(errorInfo.key, errorInfo.params))
215236
}
216237

217238
setForm(prev => ({
@@ -354,7 +375,9 @@ export const ModelAddDialog = ({ isOpen, onClose, onSuccess }: ModelAddDialogPro
354375
// Close the dialog
355376
onClose()
356377
} catch (error) {
357-
message.error(t('model.dialog.error.addFailed', { error }))
378+
const errorMessage = error instanceof Error ? error.message : String(error)
379+
const errorInfo = parseModelError(errorMessage)
380+
message.error(t(errorInfo.key, errorInfo.params))
358381
log.error(t('model.dialog.error.addFailedLog'), error)
359382
} finally {
360383
setLoading(false)

frontend/public/locales/en/common.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@
560560
"model.dialog.status.verifying": "Verifying model connectivity...",
561561
"model.dialog.success.connectivityVerified": "Model connectivity verification successful!",
562562
"model.dialog.error.connectivityRequired": "Please verify model connectivity and ensure connection is successful before adding the model",
563-
"model.dialog.error.addFailed": "Failed to add model: {{error}}",
563+
"model.dialog.error.addFailed": "Failed to add model",
564564
"model.dialog.error.addFailedLog": "Failed to add model",
565565
"model.dialog.error.noModelsFetched": "Please check your API key and network connectivity",
566566
"model.dialog.message.noModels": "Please fetch models first",

frontend/public/locales/zh/common.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@
560560
"model.dialog.warning.incompleteForm": "请先填写完整的模型配置信息",
561561
"model.dialog.status.verifying": "正在验证模型连通性...",
562562
"model.dialog.error.connectivityRequired": "请先验证模型连通性且确保连接成功后再添加模型",
563-
"model.dialog.error.addFailed": "添加模型失败:{{error}}",
563+
"model.dialog.error.addFailed": "添加模型失败",
564564
"model.dialog.error.addFailedLog": "添加模型失败",
565565
"model.dialog.error.noModelsFetched": "请检查相关API Key以及网络连通性",
566566
"model.dialog.message.noModels": "请先获取模型",

0 commit comments

Comments
 (0)