feat: add HITL status filtering and options to agent run logs

This commit is contained in:
mlogclub
2026-04-10 16:46:18 +08:00
parent b20278de29
commit eac3d87cc2
3 changed files with 47 additions and 1 deletions
@@ -34,6 +34,9 @@ func (c *AgentRunLogController) AnyList() *web.JsonResult {
params.QueryFilter{ParamName: "finalAction"}, params.QueryFilter{ParamName: "finalAction"},
params.QueryFilter{ParamName: "userMessage", Op: params.Like}, params.QueryFilter{ParamName: "userMessage", Op: params.Like},
).Desc("id") ).Desc("id")
if hitlStatus, _ := params.Get(c.Ctx, "hitlStatus"); hitlStatus != "" && hitlStatus != "all" {
cnd = services.AgentRunLogService.ApplyHITLStatusFilter(cnd, hitlStatus)
}
queryParams := params.NewQueryParams(c.Ctx) queryParams := params.NewQueryParams(c.Ctx)
queryParams.Cnd = *cnd queryParams.Cnd = *cnd
list, paging := services.AgentRunLogService.FindPageByParams(queryParams) list, paging := services.AgentRunLogService.FindPageByParams(queryParams)
@@ -3,6 +3,7 @@ package services
import ( import (
"cs-agent/internal/models" "cs-agent/internal/models"
"cs-agent/internal/repositories" "cs-agent/internal/repositories"
"strings"
"github.com/mlogclub/simple/sqls" "github.com/mlogclub/simple/sqls"
"github.com/mlogclub/simple/web/params" "github.com/mlogclub/simple/web/params"
@@ -63,3 +64,22 @@ func (s *agentRunLogService) UpdateColumn(id int64, name string, value interface
func (s *agentRunLogService) Delete(id int64) { func (s *agentRunLogService) Delete(id int64) {
repositories.AgentRunLogRepository.Delete(sqls.DB(), id) repositories.AgentRunLogRepository.Delete(sqls.DB(), id)
} }
func (s *agentRunLogService) ApplyHITLStatusFilter(cnd *sqls.Cnd, hitlStatus string) *sqls.Cnd {
if cnd == nil {
cnd = sqls.NewCnd()
}
switch strings.TrimSpace(hitlStatus) {
case "pending":
cnd.Eq("final_status", "interrupted")
case "expired":
cnd.Eq("final_status", "expired")
case "cancelled":
cnd.Where("(reply_text LIKE ? OR reply_text LIKE ?)", "%已取消本次工单创建%", "%已取消本次转人工%")
case "confirmed":
cnd.Where("resume_source <> ''")
case "triggered":
cnd.Where("interrupt_type <> ''")
}
return cnd
}
+24 -1
View File
@@ -60,6 +60,15 @@ const finalStatusOptions = [
{ value: "fallback", label: "fallback" }, { value: "fallback", label: "fallback" },
] ]
const hitlStatusOptions = [
{ value: "all", label: "全部 HITL" },
{ value: "pending", label: "等待确认" },
{ value: "confirmed", label: "已确认" },
{ value: "cancelled", label: "已取消" },
{ value: "expired", label: "已过期" },
{ value: "triggered", label: "已触发" },
]
function actionBadgeVariant(action: string) { function actionBadgeVariant(action: string) {
switch (action) { switch (action) {
case "handoff": case "handoff":
@@ -99,11 +108,13 @@ export default function DashboardAgentRunLogsPage() {
const [plannedActionInput, setPlannedActionInput] = useState("all") const [plannedActionInput, setPlannedActionInput] = useState("all")
const [finalActionInput, setFinalActionInput] = useState("all") const [finalActionInput, setFinalActionInput] = useState("all")
const [finalStatusInput, setFinalStatusInput] = useState("all") const [finalStatusInput, setFinalStatusInput] = useState("all")
const [hitlStatusInput, setHitlStatusInput] = useState("all")
const [aiAgentIdInput, setAiAgentIdInput] = useState("all") const [aiAgentIdInput, setAiAgentIdInput] = useState("all")
const [keyword, setKeyword] = useState("") const [keyword, setKeyword] = useState("")
const [plannedAction, setPlannedAction] = useState("all") const [plannedAction, setPlannedAction] = useState("all")
const [finalAction, setFinalAction] = useState("all") const [finalAction, setFinalAction] = useState("all")
const [finalStatus, setFinalStatus] = useState("all") const [finalStatus, setFinalStatus] = useState("all")
const [hitlStatus, setHitlStatus] = useState("all")
const [aiAgentId, setAiAgentId] = useState("all") const [aiAgentId, setAiAgentId] = useState("all")
const [page, setPage] = useState(1) const [page, setPage] = useState(1)
const [limit, setLimit] = useState(20) const [limit, setLimit] = useState(20)
@@ -148,6 +159,7 @@ export default function DashboardAgentRunLogsPage() {
plannedAction: plannedAction === "all" ? undefined : plannedAction, plannedAction: plannedAction === "all" ? undefined : plannedAction,
finalAction: finalAction === "all" ? undefined : finalAction, finalAction: finalAction === "all" ? undefined : finalAction,
finalStatus: finalStatus === "all" ? undefined : finalStatus, finalStatus: finalStatus === "all" ? undefined : finalStatus,
hitlStatus: hitlStatus === "all" ? undefined : hitlStatus,
aiAgentId: aiAgentId === "all" ? undefined : aiAgentId, aiAgentId: aiAgentId === "all" ? undefined : aiAgentId,
page, page,
limit, limit,
@@ -158,7 +170,7 @@ export default function DashboardAgentRunLogsPage() {
} finally { } finally {
setLoading(false) setLoading(false)
} }
}, [aiAgentId, finalAction, finalStatus, keyword, limit, page, plannedAction]) }, [aiAgentId, finalAction, finalStatus, hitlStatus, keyword, limit, page, plannedAction])
useEffect(() => { useEffect(() => {
void loadData() void loadData()
@@ -181,6 +193,7 @@ export default function DashboardAgentRunLogsPage() {
setPlannedAction(plannedActionInput) setPlannedAction(plannedActionInput)
setFinalAction(finalActionInput) setFinalAction(finalActionInput)
setFinalStatus(finalStatusInput) setFinalStatus(finalStatusInput)
setHitlStatus(hitlStatusInput)
setAiAgentId(aiAgentIdInput) setAiAgentId(aiAgentIdInput)
setPage(1) setPage(1)
} }
@@ -251,6 +264,16 @@ export default function DashboardAgentRunLogsPage() {
onChange={(value) => setFinalStatusInput(value || "all")} onChange={(value) => setFinalStatusInput(value || "all")}
/> />
</div> </div>
<div className="w-full xl:w-40">
<OptionCombobox
value={hitlStatusInput}
options={hitlStatusOptions}
placeholder="HITL 状态"
searchPlaceholder="搜索 HITL 状态"
emptyText="未找到状态"
onChange={(value) => setHitlStatusInput(value || "all")}
/>
</div>
<div className="w-full xl:w-52"> <div className="w-full xl:w-52">
<OptionCombobox <OptionCombobox
value={aiAgentIdInput} value={aiAgentIdInput}