diff --git a/src/components/AgentModal.tsx b/src/components/AgentModal.tsx index 8ede738..dd7c0e7 100644 --- a/src/components/AgentModal.tsx +++ b/src/components/AgentModal.tsx @@ -1,28 +1,257 @@ + +import { useState } from "react"; import type { Member } from "@/lib/api"; +import { updateMember, regenerateToken, revokeToken } from "@/lib/api"; interface Props { agent: Member; onClose: () => void; - onUpdated: () => void; + onUpdated: (agent: Member) => void; } -export default function AgentModal({ agent, onClose, onUpdated: _onUpdated }: Props) { +export default function AgentModal({ agent, onClose, onUpdated }: Props) { + const [name, setName] = useState(agent.name); + const [capabilities, setCapabilities] = useState( + agent.agent_config?.capabilities?.join(", ") || "" + ); + const [chatListen, setChatListen] = useState(agent.agent_config?.chat_listen || "mentions"); + const [taskListen, setTaskListen] = useState(agent.agent_config?.task_listen || "assigned"); + const [prompt, setPrompt] = useState(agent.agent_config?.prompt || ""); + const [model, setModel] = useState(agent.agent_config?.model || ""); + const [saving, setSaving] = useState(false); + const [currentToken, setCurrentToken] = useState(agent.token || null); + const [copied, setCopied] = useState(false); + const [confirmRegen, setConfirmRegen] = useState(false); + const [confirmRevoke, setConfirmRevoke] = useState(false); + + const handleSave = async () => { + setSaving(true); + try { + const caps = capabilities.split(",").map((c) => c.trim()).filter(Boolean); + const updated = await updateMember(agent.slug, { + name: name.trim(), + agent_config: { + capabilities: caps, + chat_listen: chatListen, + task_listen: taskListen, + prompt: prompt.trim() || null, + model: model.trim() || null, + }, + }); + onUpdated(updated); + onClose(); + } catch (e) { + console.error(e); + } finally { + setSaving(false); + } + }; + + const handleRegenerate = async () => { + try { + const { token } = await regenerateToken(agent.slug); + setCurrentToken(token); + setConfirmRegen(false); + } catch (e) { + console.error(e); + } + }; + + const handleRevoke = async () => { + try { + await revokeToken(agent.slug); + setCurrentToken(null); + setConfirmRevoke(false); + } catch (e) { + console.error(e); + } + }; + + const copyToken = () => { + if (currentToken) { + navigator.clipboard.writeText(currentToken); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } + }; + return ( -
-
-

Агент: {agent.name}

-

@{agent.slug}

-

Coming soon...

-
+
+
e.stopPropagation()} + > +
+
+

{agent.name}

+
@{agent.slug}
+
+ + {agent.status === "online" ? "online" : "offline"} + +
+ +
+
+ + setName(e.target.value)} + className="w-full px-3 py-2 bg-[var(--bg)] border border-[var(--border)] rounded-lg outline-none focus:border-[var(--accent)] text-sm" + /> +
+ +
+ + setCapabilities(e.target.value)} + className="w-full px-3 py-2 bg-[var(--bg)] border border-[var(--border)] rounded-lg outline-none focus:border-[var(--accent)] text-sm" + placeholder="code, review, deploy" + /> +
+ +
+
+ + +
+
+ + +
+
+ +
+ +