From 57114a2994eed776f3d536edda2fa6aa21fffbfc Mon Sep 17 00:00:00 2001
From: Autumn-27 <53844290+Autumn-27@users.noreply.github.com>
Date: Tue, 18 Aug 2026 12:38:14 -0400
Subject: [PATCH] =?UTF-8?q?feat:=20=E8=A7=A6=E5=8F=91=E5=99=A8=E6=94=AF?=
=?UTF-8?q?=E6=8C=81=E7=BC=96=E8=BE=91(=E5=89=8D=E7=AB=AF=E8=A1=A5?=
=?UTF-8?q?=E9=BD=90,=E5=90=8E=E7=AB=AF=E6=97=A9=E5=B7=B2=E6=94=AF?=
=?UTF-8?q?=E6=8C=81=20PATCH)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
触发器 Tab 之前只能新增/删除/启停。改造「新增」表单为「新增/编辑」双模式:
- 每条触发器加「编辑」按钮 → 灌入表单进入编辑态(高亮该行),改完点「保存修改」
调 api.updateTrigger;可「取消编辑」
- 编辑时保留该触发器原有启用状态;删除正在编辑的触发器会自动退出编辑态
后端 PATCH /api/triggers/{id} 与 api.updateTrigger 早已存在,本次仅补前端 UI。
---
web/src/components/agent-editor.tsx | 136 +++++++++++++++++++---------
1 file changed, 95 insertions(+), 41 deletions(-)
diff --git a/web/src/components/agent-editor.tsx b/web/src/components/agent-editor.tsx
index a678fda..ac9208e 100644
--- a/web/src/components/agent-editor.tsx
+++ b/web/src/components/agent-editor.tsx
@@ -2,7 +2,7 @@
import * as React from "react";
import { toast } from "sonner";
-import { EyeIcon, GitCompareIcon, InfoIcon, RotateCcwIcon, SaveIcon, Trash2Icon } from "lucide-react";
+import { EyeIcon, GitCompareIcon, InfoIcon, PencilIcon, RotateCcwIcon, SaveIcon, Trash2Icon, XIcon } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
@@ -768,6 +768,8 @@ function AgentTriggersTab({ agentKey, agent }: { agentKey: string; agent?: Agent
const [taskCreateMsg, setTaskCreateMsg] = React.useState("");
const [toolNames, setToolNames] = React.useState([]);
const [saving, setSaving] = React.useState(false);
+ // null = 新增模式;非 null = 正在编辑该 id 的触发器。
+ const [editingId, setEditingId] = React.useState(null);
const reload = React.useCallback(() => {
api.agentTriggers(agentKey).then(setTriggers).catch(() => setTriggers([]));
@@ -783,7 +785,46 @@ function AgentTriggersTab({ agentKey, agent }: { agentKey: string; agent?: Agent
setToolNames((prev) => (prev.includes(key) ? prev.filter((k) => k !== key) : [...prev, key]));
}
- async function create() {
+ // resetForm 清空表单并回到「新增」模式。
+ function resetForm() {
+ setEditingId(null);
+ setOnInterval(false);
+ setIntervalSec("60");
+ setOnFinding(false);
+ setOnGoalMet(false);
+ setOnTaskTimeout(false);
+ setOnToolCall(false);
+ setOnTaskCreate(false);
+ setIntervalMsg("");
+ setFindingMsg("");
+ setGoalMsg("");
+ setTaskTimeoutMsg("");
+ setToolCallMsg("");
+ setTaskCreateMsg("");
+ setToolNames([]);
+ }
+
+ // startEdit 把某条已有触发器灌进表单,进入「编辑」模式。
+ function startEdit(t: AgentTrigger) {
+ setEditingId(t.id);
+ setOnInterval(t.interval_sec > 0);
+ setIntervalSec(t.interval_sec > 0 ? String(t.interval_sec) : "60");
+ setOnFinding(t.on_finding);
+ setOnGoalMet(t.on_goal_met);
+ setOnTaskTimeout(t.on_task_timeout);
+ setOnToolCall(t.on_tool_call);
+ setOnTaskCreate(t.on_task_create);
+ setIntervalMsg(t.interval_message);
+ setFindingMsg(t.finding_message);
+ setGoalMsg(t.goal_message);
+ setTaskTimeoutMsg(t.task_timeout_message);
+ setToolCallMsg(t.tool_call_message);
+ setTaskCreateMsg(t.task_create_message);
+ setToolNames(t.tool_names ?? []);
+ }
+
+ // submit 依 editingId 走「新增」或「保存修改」;编辑时保留该触发器的启用状态。
+ async function submit() {
const n = onInterval ? Math.max(1, Math.floor(Number(intervalSec) || 0)) : 0;
if (n === 0 && !onFinding && !onGoalMet && !onTaskTimeout && !onToolCall && !onTaskCreate) {
toast.error("至少选择一种触发条件");
@@ -793,42 +834,35 @@ function AgentTriggersTab({ agentKey, agent }: { agentKey: string; agent?: Agent
toast.error("工具调用触发至少选择一个工具");
return;
}
+ const body = {
+ interval_sec: n,
+ on_finding: onFinding,
+ on_goal_met: onGoalMet,
+ on_task_timeout: onTaskTimeout,
+ on_tool_call: onToolCall,
+ on_task_create: onTaskCreate,
+ interval_message: intervalMsg.trim(),
+ finding_message: findingMsg.trim(),
+ goal_message: goalMsg.trim(),
+ task_timeout_message: taskTimeoutMsg.trim(),
+ tool_call_message: toolCallMsg.trim(),
+ task_create_message: taskCreateMsg.trim(),
+ tool_names: onToolCall ? toolNames : [],
+ };
setSaving(true);
try {
- await api.createTrigger(agentKey, {
- enabled: true,
- interval_sec: n,
- on_finding: onFinding,
- on_goal_met: onGoalMet,
- on_task_timeout: onTaskTimeout,
- on_tool_call: onToolCall,
- on_task_create: onTaskCreate,
- interval_message: intervalMsg.trim(),
- finding_message: findingMsg.trim(),
- goal_message: goalMsg.trim(),
- task_timeout_message: taskTimeoutMsg.trim(),
- tool_call_message: toolCallMsg.trim(),
- task_create_message: taskCreateMsg.trim(),
- tool_names: onToolCall ? toolNames : [],
- });
- toast.success("已添加触发器");
- setOnInterval(false);
- setIntervalSec("60");
- setOnFinding(false);
- setOnGoalMet(false);
- setOnTaskTimeout(false);
- setOnToolCall(false);
- setOnTaskCreate(false);
- setIntervalMsg("");
- setFindingMsg("");
- setGoalMsg("");
- setTaskTimeoutMsg("");
- setToolCallMsg("");
- setTaskCreateMsg("");
- setToolNames([]);
+ if (editingId != null) {
+ const cur = triggers.find((x) => x.id === editingId);
+ await api.updateTrigger(editingId, { ...body, enabled: cur?.enabled ?? true });
+ toast.success("已保存修改");
+ } else {
+ await api.createTrigger(agentKey, { ...body, enabled: true });
+ toast.success("已添加触发器");
+ }
+ resetForm();
reload();
} catch (e) {
- toast.error("添加失败:" + (e as Error).message);
+ toast.error((editingId != null ? "保存失败:" : "添加失败:") + (e as Error).message);
} finally {
setSaving(false);
}
@@ -859,6 +893,7 @@ function AgentTriggersTab({ agentKey, agent }: { agentKey: string; agent?: Agent
async function del(id: number) {
try {
await api.deleteTrigger(id);
+ if (editingId === id) resetForm();
reload();
} catch (e) {
toast.error("删除失败:" + (e as Error).message);
@@ -959,9 +994,13 @@ function AgentTriggersTab({ agentKey, agent }: { agentKey: string; agent?: Agent
- {/* 新增触发器 */}
+ {/* 新增 / 编辑触发器 */}
-
+
{/* 定时 */}
@@ -1057,10 +1096,15 @@ function AgentTriggersTab({ agentKey, agent }: { agentKey: string; agent?: Agent
)}
-
-
@@ -1069,7 +1113,13 @@ function AgentTriggersTab({ agentKey, agent }: { agentKey: string; agent?: Agent
{triggers.length === 0 &&
(暂无)}
{triggers.map((t) => (
-
+
toggleEnabled(t)} className="mt-0.5" />
@@ -1092,8 +1142,12 @@ function AgentTriggersTab({ agentKey, agent }: { agentKey: string; agent?: Agent
)}
+ startEdit(t)} title="编辑">
+
+
del(t.id)}>
+ onClick={() => del(t.id)} title="删除">