feat: enhance agent tool loop detection sensitivity, add Markdown to HTML conversion for Telegram media captions, and refine trace detail dialog UI styling.

This commit is contained in:
viettranx committed 2026-02-28 18:58:55 +07:00
1 parent 45ea0ee9a4
commit 26067d2432
4 files changed
+15 -9

No files matched your search

+3 -3
View File
@@ -10,9 +10,9 @@ import (
// Tool loop detection thresholds (per-run, not per-session).
const (
toolLoopHistorySize = 30
toolLoopWarningThreshold = 5 // inject warning into conversation
toolLoopCriticalThreshold = 10 // force stop the iteration loop
toolLoopHistorySize = 30
toolLoopWarningThreshold = 3 // inject warning into conversation
toolLoopCriticalThreshold = 5 // force stop the iteration loop
)
// toolLoopState tracks recent tool calls within a single agent run
+5 -4
View File
@@ -5,8 +5,8 @@ import "testing"
func TestToolLoopDetection_NoLoop(t *testing.T) {
var s toolLoopState
// 4 identical calls with same result → below threshold, no detection
for i := 0; i < 4; i++ {
// 2 identical calls with same result → below threshold, no detection
for i := 0; i < 2; i++ {
h := s.record("list_files", map[string]interface{}{"path": "."})
s.recordResult(h, "access denied")
level, _ := s.detect("list_files", h)
@@ -77,7 +77,8 @@ func TestToolLoopDetection_MixedTools(t *testing.T) {
var s toolLoopState
// Alternate between two tools with same result → each tool only hit ~half
for i := 0; i < 15; i++ {
// With 8 iterations, each tool is called 4 times → below critical (5)
for i := 0; i < 8; i++ {
toolName := "list_files"
if i%2 == 1 {
toolName = "read_file"
@@ -85,7 +86,7 @@ func TestToolLoopDetection_MixedTools(t *testing.T) {
h := s.record(toolName, map[string]interface{}{"path": "."})
s.recordResult(h, "error")
level, _ := s.detect(toolName, h)
// Each tool is only called ~7-8 times, should at most warn
// Each tool is only called 4 times, should at most warn
if level == "critical" {
t.Fatalf("iteration %d: unexpected critical for alternating tools", i)
}
+5
View File
@@ -137,6 +137,11 @@ func (c *Channel) sendMediaMessage(ctx context.Context, chatID int64, msg bus.Ou
msg.Content = "" // only use for first media
}
// Convert caption from markdown to Telegram HTML (same as regular messages)
if caption != "" {
caption = markdownToTelegramHTML(caption)
}
// Split caption if too long (Telegram limit: 1024 chars)
var followUpText string
if len(caption) > telegramCaptionMaxLen {
@@ -176,7 +176,7 @@ function SpanTreeNode({ node, depth }: { node: SpanNode; depth: number }) {
return (
<div>
<div
className="mt-1.5 rounded-md border text-sm"
className="mt-1.5 min-w-0 rounded-md border text-sm"
style={{ marginLeft: depth * 24 }}
>
<div className="flex w-full items-center gap-1 px-2 py-2">
@@ -233,7 +233,7 @@ function SpanTreeNode({ node, depth }: { node: SpanNode; depth: number }) {
{/* Expanded detail panel */}
{detailOpen && (
<div className="space-y-2 border-t px-3 py-2">
<div className="space-y-2 overflow-hidden border-t px-3 py-2">
{span.model && (
<div className="text-xs">
<span className="text-muted-foreground">Model:</span> {span.provider}/{span.model}