From aaa56ff004cdc9fcaee82c676d6a54835662f22a Mon Sep 17 00:00:00 2001 From: viettranx Date: Tue, 31 Mar 2026 23:07:15 +0700 Subject: [PATCH] fix(ui): summoning modal mode, dialog widths, and MCP refresh animation - Add mode prop to SummoningModal (summon vs regenerate) so Edit with AI shows appropriate text instead of summoning language - Fix memory document and KG entity detail dialogs using sm:max-w-* to properly override base sm:max-w-lg from DialogContent - Expose isFetching from useMCP hook so refresh button animation works --- ui/web/src/i18n/locales/en/agents.json | 7 ++++++- ui/web/src/i18n/locales/vi/agents.json | 7 ++++++- ui/web/src/i18n/locales/zh/agents.json | 7 ++++++- .../agents/agent-detail/agent-detail-page.tsx | 4 ++++ ui/web/src/pages/agents/summoning-modal.tsx | 16 ++++++++++------ ui/web/src/pages/mcp/hooks/use-mcp.ts | 3 ++- ui/web/src/pages/mcp/mcp-page.tsx | 4 ++-- .../src/pages/memory/kg-entity-detail-dialog.tsx | 2 +- .../src/pages/memory/memory-document-dialog.tsx | 2 +- 9 files changed, 38 insertions(+), 14 deletions(-) diff --git a/ui/web/src/i18n/locales/en/agents.json b/ui/web/src/i18n/locales/en/agents.json index f8b01c2c..8aff8ee3 100644 --- a/ui/web/src/i18n/locales/en/agents.json +++ b/ui/web/src/i18n/locales/en/agents.json @@ -533,7 +533,12 @@ "retrying": "Retrying...", "done": "done", "fileLabelSOUL": "Soul & Personality", - "fileLabelIDENTITY": "Identity Card" + "fileLabelIDENTITY": "Identity Card", + "regenerateTitle": "Editing with AI...", + "regenerateCompleted": "Edit Complete!", + "regenerateFailed": "Edit Failed", + "regenerateWeavingSoul": "Updating files for", + "regenerateWait": "AI is rewriting the files. Please wait..." }, "configGroups": { "core": "Core", diff --git a/ui/web/src/i18n/locales/vi/agents.json b/ui/web/src/i18n/locales/vi/agents.json index 386d0716..16c27939 100644 --- a/ui/web/src/i18n/locales/vi/agents.json +++ b/ui/web/src/i18n/locales/vi/agents.json @@ -533,7 +533,12 @@ "retrying": "Đang thử lại...", "done": "xong", "fileLabelSOUL": "Linh hồn & Tính cách", - "fileLabelIDENTITY": "Thẻ danh tính" + "fileLabelIDENTITY": "Thẻ danh tính", + "regenerateTitle": "Đang chỉnh sửa bằng AI...", + "regenerateCompleted": "Chỉnh sửa hoàn tất!", + "regenerateFailed": "Chỉnh sửa thất bại", + "regenerateWeavingSoul": "Đang cập nhật tệp cho", + "regenerateWait": "AI đang viết lại các tệp. Vui lòng chờ..." }, "configGroups": { "core": "Cốt lõi", diff --git a/ui/web/src/i18n/locales/zh/agents.json b/ui/web/src/i18n/locales/zh/agents.json index 63d947e9..a6b8d04f 100644 --- a/ui/web/src/i18n/locales/zh/agents.json +++ b/ui/web/src/i18n/locales/zh/agents.json @@ -533,7 +533,12 @@ "retrying": "重试中...", "done": "完成", "fileLabelSOUL": "灵魂与个性", - "fileLabelIDENTITY": "身份卡" + "fileLabelIDENTITY": "身份卡", + "regenerateTitle": "AI 编辑中...", + "regenerateCompleted": "编辑完成!", + "regenerateFailed": "编辑失败", + "regenerateWeavingSoul": "正在更新文件:", + "regenerateWait": "AI 正在重写文件,请稍候..." }, "configGroups": { "core": "核心", diff --git a/ui/web/src/pages/agents/agent-detail/agent-detail-page.tsx b/ui/web/src/pages/agents/agent-detail/agent-detail-page.tsx index e7dd6360..6a6e22a0 100644 --- a/ui/web/src/pages/agents/agent-detail/agent-detail-page.tsx +++ b/ui/web/src/pages/agents/agent-detail/agent-detail-page.tsx @@ -30,6 +30,7 @@ export function AgentDetailPage({ agentId, onBack }: AgentDetailPageProps) { const { deleteAgent: deleteAgentById } = useAgents(); const hb = useAgentHeartbeat(agentId); const [summoningOpen, setSummoningOpen] = useState(false); + const [summoningMode, setSummoningMode] = useState<"summon" | "regenerate">("summon"); const [activeTab, setActiveTab] = useState("agent"); const [deleteOpen, setDeleteOpen] = useState(false); const [advancedOpen, setAdvancedOpen] = useState(false); @@ -37,11 +38,13 @@ export function AgentDetailPage({ agentId, onBack }: AgentDetailPageProps) { const handleRegenerate = async (prompt: string) => { await regenerateAgent(prompt); + setSummoningMode("regenerate"); setSummoningOpen(true); }; const handleResummon = async () => { await resummonAgent(); + setSummoningMode("summon"); setSummoningOpen(true); }; @@ -130,6 +133,7 @@ export function AgentDetailPage({ agentId, onBack }: AgentDetailPageProps) { agentName={title} onCompleted={() => {}} onResummon={async () => { await resummonAgent(); }} + mode={summoningMode} /> {heartbeatOpen && ( diff --git a/ui/web/src/pages/agents/summoning-modal.tsx b/ui/web/src/pages/agents/summoning-modal.tsx index a76883a3..e0d40d8d 100644 --- a/ui/web/src/pages/agents/summoning-modal.tsx +++ b/ui/web/src/pages/agents/summoning-modal.tsx @@ -19,6 +19,8 @@ interface SummoningModalProps { onResummon: (agentId: string) => Promise; hideClose?: boolean; onContinue?: () => void; + /** "summon" (default) shows summoning language; "regenerate" shows edit-with-AI language */ + mode?: "summon" | "regenerate"; } const SUMMONING_FILES = [ @@ -35,7 +37,9 @@ export function SummoningModal({ onResummon, hideClose = false, onContinue, + mode = "summon", }: SummoningModalProps) { + const isRegenerate = mode === "regenerate"; const { t } = useTranslation("agents"); const [generatedFiles, setGeneratedFiles] = useState([]); const [status, setStatus] = useState<"summoning" | "completed" | "failed">("summoning"); @@ -120,10 +124,10 @@ export function SummoningModal({ {status === "completed" - ? t("summoning.completed") + ? t(isRegenerate ? "summoning.regenerateCompleted" : "summoning.completed") : status === "failed" - ? t("summoning.failed") - : t("summoning.title")} + ? t(isRegenerate ? "summoning.regenerateFailed" : "summoning.failed") + : t(isRegenerate ? "summoning.regenerateTitle" : "summoning.title")} @@ -165,7 +169,7 @@ export function SummoningModal({ : { duration: 0.5 } } > - {status === "completed" ? "\u2728" : status === "failed" ? "\u{1F4A8}" : "\u{1FA84}"} + {status === "completed" ? "\u2728" : status === "failed" ? "\u{1F4A8}" : isRegenerate ? "\u270F\uFE0F" : "\u{1FA84}"} @@ -180,7 +184,7 @@ export function SummoningModal({ {errorMsg || t("summoning.failed")} ) : ( - <>{t("summoning.weavingSoul")} {agentName}... + <>{t(isRegenerate ? "summoning.regenerateWeavingSoul" : "summoning.weavingSoul")} {agentName}... )}

@@ -231,7 +235,7 @@ export function SummoningModal({ {status === "summoning" && (

- {t("summoning.wait")} ({Math.floor(elapsed / 60)}:{String(elapsed % 60).padStart(2, "0")}) + {t(isRegenerate ? "summoning.regenerateWait" : "summoning.wait")} ({Math.floor(elapsed / 60)}:{String(elapsed % 60).padStart(2, "0")})

)} diff --git a/ui/web/src/pages/mcp/hooks/use-mcp.ts b/ui/web/src/pages/mcp/hooks/use-mcp.ts index 3af2e3f3..8e5247fe 100644 --- a/ui/web/src/pages/mcp/hooks/use-mcp.ts +++ b/ui/web/src/pages/mcp/hooks/use-mcp.ts @@ -12,7 +12,7 @@ export function useMCP() { const http = useHttp(); const queryClient = useQueryClient(); - const { data: servers = [], isLoading: loading } = useQuery({ + const { data: servers = [], isLoading: loading, isFetching: fetching } = useQuery({ queryKey: queryKeys.mcp.all, queryFn: async () => { const res = await http.get<{ servers: MCPServerData[] }>("/v1/mcp/servers"); @@ -157,6 +157,7 @@ export function useMCP() { return { servers, loading, + fetching, refresh: invalidate, createServer, updateServer, diff --git a/ui/web/src/pages/mcp/mcp-page.tsx b/ui/web/src/pages/mcp/mcp-page.tsx index f13878e1..86f1ef23 100644 --- a/ui/web/src/pages/mcp/mcp-page.tsx +++ b/ui/web/src/pages/mcp/mcp-page.tsx @@ -27,8 +27,8 @@ const transportBadge: Record = { export function MCPPage() { const { t } = useTranslation("mcp"); const { t: tc } = useTranslation("common"); - const { servers, loading, refresh, createServer, updateServer, deleteServer, grantAgent, revokeAgent, listAgentGrants, testConnection, reconnectServer, listServerTools, getUserCredentials, setUserCredentials, deleteUserCredentials } = useMCP(); - const spinning = useMinLoading(loading); + const { servers, loading, fetching, refresh, createServer, updateServer, deleteServer, grantAgent, revokeAgent, listAgentGrants, testConnection, reconnectServer, listServerTools, getUserCredentials, setUserCredentials, deleteUserCredentials } = useMCP(); + const spinning = useMinLoading(fetching); const showSkeleton = useDeferredLoading(loading && servers.length === 0); const [search, setSearch] = useState(""); const [formOpen, setFormOpen] = useState(false); diff --git a/ui/web/src/pages/memory/kg-entity-detail-dialog.tsx b/ui/web/src/pages/memory/kg-entity-detail-dialog.tsx index 9881c1d5..325928b5 100644 --- a/ui/web/src/pages/memory/kg-entity-detail-dialog.tsx +++ b/ui/web/src/pages/memory/kg-entity-detail-dialog.tsx @@ -84,7 +84,7 @@ export function KGEntityDetailDialog({ open, onOpenChange, agentId, entity, getE return ( !traversing && onOpenChange(v)}> - + {entity?.name} diff --git a/ui/web/src/pages/memory/memory-document-dialog.tsx b/ui/web/src/pages/memory/memory-document-dialog.tsx index 8221b283..878d28f8 100644 --- a/ui/web/src/pages/memory/memory-document-dialog.tsx +++ b/ui/web/src/pages/memory/memory-document-dialog.tsx @@ -108,7 +108,7 @@ export function MemoryDocumentDialog({ open, onOpenChange, agentId, document }: return ( !saving && onOpenChange(v)}> - + {document?.path}