fix: remove capabilities/prompt/model from agent modal, add mentionable

This commit is contained in:
Markov 2026-03-15 13:08:50 +01:00
parent be2b073e4c
commit c00a3ea1f1

View File

@ -1,4 +1,3 @@
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import type { Member, Label } from "@/lib/api"; import type { Member, Label } from "@/lib/api";
import { updateMember, regenerateToken, revokeToken, getLabels } from "@/lib/api"; import { updateMember, regenerateToken, revokeToken, getLabels } from "@/lib/api";
@ -13,13 +12,9 @@ export default function AgentModal({ agent, onClose, onUpdated }: Props) {
const [name, setName] = useState(agent.name); const [name, setName] = useState(agent.name);
const [slug, setSlug] = useState(agent.slug); const [slug, setSlug] = useState(agent.slug);
const [slugError, setSlugError] = useState(""); const [slugError, setSlugError] = useState("");
const [capabilities, setCapabilities] = useState(
agent.agent_config?.capabilities?.join(", ") || ""
);
const [chatListen, setChatListen] = useState(agent.agent_config?.chat_listen || "mentions"); const [chatListen, setChatListen] = useState(agent.agent_config?.chat_listen || "mentions");
const [taskListen, setTaskListen] = useState(agent.agent_config?.task_listen || "assigned"); const [taskListen, setTaskListen] = useState(agent.agent_config?.task_listen || "assigned");
const [prompt, setPrompt] = useState(agent.agent_config?.prompt || ""); const [mentionable, setMentionable] = useState(agent.agent_config?.mentionable ?? true);
const [model, setModel] = useState(agent.agent_config?.model || "");
const [saving, setSaving] = useState(false); const [saving, setSaving] = useState(false);
const [currentToken, setCurrentToken] = useState<string | null>(agent.token || null); const [currentToken, setCurrentToken] = useState<string | null>(agent.token || null);
const [copied, setCopied] = useState(false); const [copied, setCopied] = useState(false);
@ -35,7 +30,6 @@ export default function AgentModal({ agent, onClose, onUpdated }: Props) {
const handleSave = async () => { const handleSave = async () => {
setSaving(true); setSaving(true);
try { try {
const caps = capabilities.split(",").map((c) => c.trim()).filter(Boolean);
const trimmedSlug = slug.trim().toLowerCase().replace(/[^a-z0-9_-]/g, ''); const trimmedSlug = slug.trim().toLowerCase().replace(/[^a-z0-9_-]/g, '');
if (!trimmedSlug) { if (!trimmedSlug) {
setSlugError("Slug не может быть пустым"); setSlugError("Slug не может быть пустым");
@ -45,12 +39,10 @@ export default function AgentModal({ agent, onClose, onUpdated }: Props) {
name: name.trim(), name: name.trim(),
slug: trimmedSlug !== agent.slug ? trimmedSlug : undefined, slug: trimmedSlug !== agent.slug ? trimmedSlug : undefined,
agent_config: { agent_config: {
capabilities: caps,
labels: agentLabels, labels: agentLabels,
chat_listen: chatListen, chat_listen: chatListen,
task_listen: taskListen, task_listen: taskListen,
prompt: prompt.trim() || null, mentionable,
model: model.trim() || null,
}, },
}); });
onUpdated(updated); onUpdated(updated);
@ -97,13 +89,13 @@ export default function AgentModal({ agent, onClose, onUpdated }: Props) {
return ( return (
<div className="fixed inset-0 bg-black/60 flex items-center justify-center z-50" onClick={onClose}> <div className="fixed inset-0 bg-black/60 flex items-center justify-center z-50" onClick={onClose}>
<div <div
className="bg-[var(--card)] border border-[var(--border)] rounded-xl w-full max-w-lg" className="bg-[var(--card)] border border-[var(--border)] rounded-xl w-full max-w-lg max-h-[90vh] overflow-y-auto"
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
> >
<div className="p-5 border-b border-[var(--border)] flex items-center justify-between"> <div className="p-5 border-b border-[var(--border)] flex items-center justify-between">
<div> <div>
<h2 className="text-lg font-bold">{agent.name}</h2> <h2 className="text-lg font-bold">{agent.name}</h2>
<div className="text-xs text-[var(--muted)]">@{agent.slug}</div> <div className="text-xs text-[var(--muted)]">@{agent.slug} {agent.type}</div>
</div> </div>
<span <span
className={`text-xs px-2 py-0.5 rounded-full ${ className={`text-xs px-2 py-0.5 rounded-full ${
@ -137,16 +129,6 @@ export default function AgentModal({ agent, onClose, onUpdated }: Props) {
{slugError && <div className="text-xs text-red-400 mt-1">{slugError}</div>} {slugError && <div className="text-xs text-red-400 mt-1">{slugError}</div>}
</div> </div>
<div>
<label className="block text-sm text-[var(--muted)] mb-1">Capabilities</label>
<input
value={capabilities}
onChange={(e) => 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"
/>
</div>
{/* Labels */} {/* Labels */}
{allLabels.length > 0 && ( {allLabels.length > 0 && (
<div> <div>
@ -177,51 +159,41 @@ export default function AgentModal({ agent, onClose, onUpdated }: Props) {
<div className="grid grid-cols-2 gap-3"> <div className="grid grid-cols-2 gap-3">
<div> <div>
<label className="block text-sm text-[var(--muted)] mb-1">Chat listen</label> <label className="block text-sm text-[var(--muted)] mb-1">Чат</label>
<select <select
value={chatListen} value={chatListen}
onChange={(e) => setChatListen(e.target.value)} onChange={(e) => setChatListen(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" className="w-full px-3 py-2 bg-[var(--bg)] border border-[var(--border)] rounded-lg outline-none focus:border-[var(--accent)] text-sm"
> >
<option value="all">all</option> <option value="all">Все сообщения</option>
<option value="mentions">mentions</option> <option value="mentions">Только @упоминания</option>
<option value="none">none</option> <option value="none">Не слушать</option>
</select> </select>
</div> </div>
<div> <div>
<label className="block text-sm text-[var(--muted)] mb-1">Task listen</label> <label className="block text-sm text-[var(--muted)] mb-1">Задачи</label>
<select <select
value={taskListen} value={taskListen}
onChange={(e) => setTaskListen(e.target.value)} onChange={(e) => setTaskListen(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" className="w-full px-3 py-2 bg-[var(--bg)] border border-[var(--border)] rounded-lg outline-none focus:border-[var(--accent)] text-sm"
> >
<option value="all">all</option> <option value="all">Все задачи</option>
<option value="assigned">assigned</option> <option value="assigned">Назначенные</option>
<option value="none">none</option> <option value="none">Не слушать</option>
</select> </select>
</div> </div>
</div> </div>
<div> {/* Mentionable */}
<label className="block text-sm text-[var(--muted)] mb-1">Prompt</label> <label className="flex items-center gap-2 cursor-pointer">
<textarea
value={prompt}
onChange={(e) => setPrompt(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 resize-y min-h-[60px]"
rows={3}
placeholder="Системный промпт агента..."
/>
</div>
<div>
<label className="block text-sm text-[var(--muted)] mb-1">Модель</label>
<input <input
value={model} type="checkbox"
onChange={(e) => setModel(e.target.value)} checked={mentionable}
className="w-full px-3 py-2 bg-[var(--bg)] border border-[var(--border)] rounded-lg outline-none focus:border-[var(--accent)] text-sm" onChange={(e) => setMentionable(e.target.checked)}
placeholder="claude-sonnet-4-20250514, gpt-4o, ..." className="accent-[var(--accent)]"
/> />
</div> <span className="text-sm">Можно @упоминать</span>
</label>
{/* Token section */} {/* Token section */}
<div className="pt-3 border-t border-[var(--border)]"> <div className="pt-3 border-t border-[var(--border)]">
@ -231,7 +203,7 @@ export default function AgentModal({ agent, onClose, onUpdated }: Props) {
<div className="p-3 bg-[var(--bg)] border border-[var(--border)] rounded-lg font-mono text-xs break-all select-all mb-2"> <div className="p-3 bg-[var(--bg)] border border-[var(--border)] rounded-lg font-mono text-xs break-all select-all mb-2">
{currentToken} {currentToken}
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2 flex-wrap">
<button <button
onClick={copyToken} onClick={copyToken}
className="px-3 py-1.5 bg-[var(--accent)] text-white rounded text-xs hover:opacity-90" className="px-3 py-1.5 bg-[var(--accent)] text-white rounded text-xs hover:opacity-90"