From 4e764350a4c368c6f605f3e9daff269ab480d811 Mon Sep 17 00:00:00 2001 From: xuhd Date: Thu, 14 May 2026 12:59:10 +0800 Subject: [PATCH] =?UTF-8?q?feat(agents):=20=E5=88=9B=E5=BB=BA=E4=B8=93?= =?UTF-8?q?=E5=AE=B6=E9=A1=B5=E9=9D=A2=E5=8A=A0=E6=A8=A1=E5=9E=8B=E9=80=89?= =?UTF-8?q?=E6=8B=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NewAgentPage 在两处加 Select 下拉: - 左侧聊天框上方 "当前对话模型":透传给 useThreadStream 的 context.model_name,控制当前 bootstrap 对话调用的 LLM - 右侧表单 "模型":写入 agent.model,控制专家保存后被使用时调用 的 LLM 两个下拉互相独立,复用 useModels() 拉 /api/models。页面加载完 模型列表后自动 seed 到列表第一个(与 config.yaml 全局默认对齐), 用户可随时切换。 杂项:.gitignore 忽略 skills/ 与 hermes-agent-main/ 运行时目录。 Co-Authored-By: Claude Opus 4.7 (1M context) --- .gitignore | 4 ++ frontend-web/src/pages/NewAgentPage.tsx | 74 ++++++++++++++++++++++++- 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4fd1ef9e..bde62f5d 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,7 @@ offline-backend-20260512/backend/.deer-flow/* offline-backend-20260512/start_backend.sh offline-backend-20260512/stop_backend.sh offline-backend-20260512/check_backend.sh + +skills/ +hermes-agent-main/ +.gitignore diff --git a/frontend-web/src/pages/NewAgentPage.tsx b/frontend-web/src/pages/NewAgentPage.tsx index f60e7642..e64de2bc 100644 --- a/frontend-web/src/pages/NewAgentPage.tsx +++ b/frontend-web/src/pages/NewAgentPage.tsx @@ -17,6 +17,13 @@ import { } from "@/components/ai-elements/prompt-input"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; import { Textarea } from "@/components/ui/textarea"; import { ArtifactsProvider } from "@/components/workspace/artifacts"; import { @@ -33,6 +40,7 @@ import { updateAgent, } from "@/core/agents/api"; import { useI18n } from "@/core/i18n/hooks"; +import { useModels } from "@/core/models/hooks"; import type { Skill } from "@/core/skills"; import { useSkills } from "@/core/skills/hooks"; import { useThreadStream } from "@/core/threads/hooks"; @@ -63,6 +71,8 @@ export default function NewAgentPage() { const [nameInput, setNameInput] = useState(""); const [descriptionInput, setDescriptionInput] = useState(""); const [soulInput, setSoulInput] = useState(""); + const [modelInput, setModelInput] = useState(""); + const [chatModelInput, setChatModelInput] = useState(""); const [formError, setFormError] = useState(""); const [agentId, setAgentId] = useState(""); const [agent, setAgent] = useState(null); @@ -72,6 +82,7 @@ export default function NewAgentPage() { const [isSkillSelectionTouched, setIsSkillSelectionTouched] = useState(false); const [threadPrepared, setThreadPrepared] = useState(false); const { skills, isLoading: isSkillsLoading } = useSkills(); + const { models, isLoading: isModelsLoading } = useModels(); const enabledSkills = useMemo( () => skills.filter((skill) => skill.enabled), @@ -89,12 +100,24 @@ export default function NewAgentPage() { ); }, [enabledSkills, isSkillSelectionTouched]); + // Seed both model selectors with the first available model the first time + // models load. The user can still change either independently afterwards. + useEffect(() => { + if (models.length === 0) { + return; + } + const first = models[0]!.name; + setModelInput((prev) => prev || first); + setChatModelInput((prev) => prev || first); + }, [models]); + const [thread, sendMessage] = useThreadStream({ threadId, assistantId: agentId || undefined, context: { mode: "flash", is_bootstrap: true, + model_name: chatModelInput || undefined, }, onToolEnd() { // setup_agent never actually executes in this flow — it gets @@ -140,6 +163,8 @@ export default function NewAgentPage() { name = `未命名专家-${Date.now().toString(36)}`; } + const modelOverride = modelInput.trim() || null; + if (agentId) { setIsSavingDraft(true); try { @@ -148,6 +173,7 @@ export default function NewAgentPage() { description: descriptionInput, soul: soulInput, skills: selectedSkills, + model: modelOverride, }); setAgent(updated); return updated; @@ -167,6 +193,7 @@ export default function NewAgentPage() { description: descriptionInput, soul: soulInput, skills: selectedSkills, + model: modelOverride, }); setAgentId(created.id); setAgent(created); @@ -193,6 +220,7 @@ export default function NewAgentPage() { }, [ agentId, descriptionInput, + modelInput, selectedSkills, soulInput, t.agents.nameStepCheckError, @@ -305,7 +333,28 @@ export default function NewAgentPage() { onSetupAgentReject={handleRejectSetupAgent} /> -
+
+
+ + 当前对话模型 + + +
void handleChatSubmit(text)} > @@ -354,6 +403,29 @@ export default function NewAgentPage() { />
+
+ + +

+ 该专家被使用时调用的模型。 +

+
+