mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-11 03:13:24 +00:00
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
This commit is contained in:
1 parent
ef0de0d760
commit
aaa56ff004
9 files changed
+38
-14
No files matched your search
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -533,7 +533,12 @@
|
||||
"retrying": "重试中...",
|
||||
"done": "完成",
|
||||
"fileLabelSOUL": "灵魂与个性",
|
||||
"fileLabelIDENTITY": "身份卡"
|
||||
"fileLabelIDENTITY": "身份卡",
|
||||
"regenerateTitle": "AI 编辑中...",
|
||||
"regenerateCompleted": "编辑完成!",
|
||||
"regenerateFailed": "编辑失败",
|
||||
"regenerateWeavingSoul": "正在更新文件:",
|
||||
"regenerateWait": "AI 正在重写文件,请稍候..."
|
||||
},
|
||||
"configGroups": {
|
||||
"core": "核心",
|
||||
|
||||
@@ -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 && (
|
||||
|
||||
@@ -19,6 +19,8 @@ interface SummoningModalProps {
|
||||
onResummon: (agentId: string) => Promise<void>;
|
||||
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<string[]>([]);
|
||||
const [status, setStatus] = useState<"summoning" | "completed" | "failed">("summoning");
|
||||
@@ -120,10 +124,10 @@ export function SummoningModal({
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-center">
|
||||
{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")}
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
@@ -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}"}
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
@@ -180,7 +184,7 @@ export function SummoningModal({
|
||||
{errorMsg || t("summoning.failed")}
|
||||
</span>
|
||||
) : (
|
||||
<>{t("summoning.weavingSoul")} <span className="font-semibold text-foreground">{agentName}</span>...</>
|
||||
<>{t(isRegenerate ? "summoning.regenerateWeavingSoul" : "summoning.weavingSoul")} <span className="font-semibold text-foreground">{agentName}</span>...</>
|
||||
)}
|
||||
</p>
|
||||
|
||||
@@ -231,7 +235,7 @@ export function SummoningModal({
|
||||
|
||||
{status === "summoning" && (
|
||||
<p className="text-center text-xs text-muted-foreground tabular-nums">
|
||||
{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")})
|
||||
</p>
|
||||
)}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -27,8 +27,8 @@ const transportBadge: Record<string, string> = {
|
||||
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);
|
||||
|
||||
@@ -84,7 +84,7 @@ export function KGEntityDetailDialog({ open, onOpenChange, agentId, entity, getE
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={(v) => !traversing && onOpenChange(v)}>
|
||||
<DialogContent aria-describedby={undefined} className="max-w-7xl max-h-[90vh] flex flex-col">
|
||||
<DialogContent aria-describedby={undefined} className="max-h-[90vh] w-[95vw] flex flex-col sm:max-w-5xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center gap-2">
|
||||
<span>{entity?.name}</span>
|
||||
|
||||
@@ -108,7 +108,7 @@ export function MemoryDocumentDialog({ open, onOpenChange, agentId, document }:
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={(v) => !saving && onOpenChange(v)}>
|
||||
<DialogContent aria-describedby={undefined} className="max-w-4xl max-h-[85vh] flex flex-col">
|
||||
<DialogContent aria-describedby={undefined} className="max-h-[85vh] w-[95vw] flex flex-col sm:max-w-4xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center gap-2">
|
||||
<span className="font-mono text-sm">{document?.path}</span>
|
||||
|
||||
Reference in new issue
Block a user