mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-06-12 12:10:58 +00:00
feat(agent): adaptive tool timing with slow tool notification
Track per-tool execution time statistics in session metadata. When a tool call exceeds its adaptive threshold (2x historical max, min 120s default), send a direct outbound notification to the user. - ToolTimingMap: parse/serialize/record/threshold from session metadata - StartSlowTimer: fires once per tool call, auto-cancels on completion - Team config: slow_tool toggle (default on, always direct, never leader) - UI: toggle in team settings with i18n (en/vi/zh) - Store: add GetSessionMetadata to session store interface
This commit is contained in:
@@ -189,6 +189,8 @@
|
||||
"notifyProgressHint": "Notify when a member updates task progress.",
|
||||
"notifyFailed": "Task failed",
|
||||
"notifyFailedHint": "Notify when a task fails.",
|
||||
"notifySlowTool": "Slow tool alert",
|
||||
"notifySlowToolHint": "System alert when a tool call takes abnormally long. Always direct — never through leader.",
|
||||
"notifyMode": "Delivery mode",
|
||||
"notifyModeHint": "How notifications are delivered to the chat channel.",
|
||||
"notifyModeDirect": "Direct",
|
||||
|
||||
@@ -189,6 +189,8 @@
|
||||
"notifyProgressHint": "Thông báo khi thành viên cập nhật tiến trình.",
|
||||
"notifyFailed": "Thất bại",
|
||||
"notifyFailedHint": "Thông báo khi nhiệm vụ thất bại.",
|
||||
"notifySlowTool": "Cảnh báo tool chạy lâu",
|
||||
"notifySlowToolHint": "Thông báo hệ thống khi tool chạy lâu bất thường. Luôn gửi trực tiếp — không qua leader.",
|
||||
"notifyMode": "Chế độ gửi",
|
||||
"notifyModeHint": "Cách thông báo được gửi đến kênh chat.",
|
||||
"notifyModeDirect": "Trực tiếp",
|
||||
|
||||
@@ -189,6 +189,8 @@
|
||||
"notifyProgressHint": "成员更新进度时通知。",
|
||||
"notifyFailed": "任务失败",
|
||||
"notifyFailedHint": "任务失败时通知。",
|
||||
"notifySlowTool": "工具慢速警报",
|
||||
"notifySlowToolHint": "工具调用异常耗时时发送系统警报。始终直接发送,不通过 leader。",
|
||||
"notifyMode": "发送方式",
|
||||
"notifyModeHint": "通知如何发送到聊天频道。",
|
||||
"notifyModeDirect": "直接发送",
|
||||
|
||||
@@ -75,6 +75,7 @@ export function TeamSettingsTab({ teamId, team, onSaved }: TeamSettingsTabProps)
|
||||
const [notifyDispatched, setNotifyDispatched] = useState(initNotify.dispatched ?? true);
|
||||
const [notifyProgress, setNotifyProgress] = useState(initNotify.progress ?? true);
|
||||
const [notifyFailed, setNotifyFailed] = useState(initNotify.failed ?? true);
|
||||
const [notifySlowTool, setNotifySlowTool] = useState(initNotify.slow_tool ?? true);
|
||||
const [notifyMode, setNotifyMode] = useState<"direct" | "leader">(initNotify.mode ?? "direct");
|
||||
const [escalationMode, setEscalationMode] = useState<EscalationMode | "">(initial.escalation_mode ?? "");
|
||||
const [escalationActions, setEscalationActions] = useState<EscalationAction[]>(initial.escalation_actions ?? []);
|
||||
@@ -105,6 +106,7 @@ export function TeamSettingsTab({ teamId, team, onSaved }: TeamSettingsTabProps)
|
||||
setNotifyDispatched(sn.dispatched ?? true);
|
||||
setNotifyProgress(sn.progress ?? true);
|
||||
setNotifyFailed(sn.failed ?? true);
|
||||
setNotifySlowTool(sn.slow_tool ?? true);
|
||||
setNotifyMode(sn.mode ?? "direct");
|
||||
setEscalationMode(s.escalation_mode ?? "");
|
||||
setEscalationActions(s.escalation_actions ?? []);
|
||||
@@ -129,6 +131,7 @@ export function TeamSettingsTab({ teamId, team, onSaved }: TeamSettingsTabProps)
|
||||
dispatched: notifyDispatched,
|
||||
progress: notifyProgress,
|
||||
failed: notifyFailed,
|
||||
slow_tool: notifySlowTool,
|
||||
mode: notifyMode,
|
||||
};
|
||||
if (escalationMode) {
|
||||
@@ -148,7 +151,7 @@ export function TeamSettingsTab({ teamId, team, onSaved }: TeamSettingsTabProps)
|
||||
} finally {
|
||||
setSaving(false);
|
||||
}
|
||||
}, [teamId, version, allowUserIds, denyUserIds, allowChannels, denyChannels, notifyDispatched, notifyProgress, notifyFailed, notifyMode, escalationMode, escalationActions, followupInterval, followupMaxReminders, workspaceScope, updateTeamSettings, onSaved, t]);
|
||||
}, [teamId, version, allowUserIds, denyUserIds, allowChannels, denyChannels, notifyDispatched, notifyProgress, notifyFailed, notifySlowTool, notifyMode, escalationMode, escalationActions, followupInterval, followupMaxReminders, workspaceScope, updateTeamSettings, onSaved, t]);
|
||||
|
||||
const userOptions = knownUsers.map((u) => ({ value: u, label: u }));
|
||||
const channelOptions = CHANNEL_TYPES.map((c) => ({ value: c.value, label: c.label }));
|
||||
@@ -235,6 +238,13 @@ export function TeamSettingsTab({ teamId, team, onSaved }: TeamSettingsTabProps)
|
||||
</div>
|
||||
<Switch checked={notifyFailed} onCheckedChange={setNotifyFailed} />
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<span className="text-sm font-semibold">{t("settings.notifySlowTool")}</span>
|
||||
<p className="text-xs text-muted-foreground">{t("settings.notifySlowToolHint")}</p>
|
||||
</div>
|
||||
<Switch checked={notifySlowTool} onCheckedChange={setNotifySlowTool} />
|
||||
</div>
|
||||
<div className="border-t pt-3 space-y-2">
|
||||
<span className="text-sm font-semibold">{t("settings.notifyMode")}</span>
|
||||
<div className="grid grid-cols-1 gap-2 sm:grid-cols-2">
|
||||
|
||||
@@ -9,6 +9,7 @@ export interface TeamNotifyConfig {
|
||||
dispatched?: boolean;
|
||||
progress?: boolean;
|
||||
failed?: boolean;
|
||||
slow_tool?: boolean;
|
||||
mode?: "direct" | "leader";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user