mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-08-01 16:38:48 +02:00
Add files via upload
This commit is contained in:
@@ -588,11 +588,14 @@ func runEinoADKAgentLoop(ctx context.Context, args *einoADKRunLoopArgs, baseMsgs
|
||||
zap.Duration("backoff", backoff))
|
||||
}
|
||||
if progress != nil {
|
||||
progress("eino_run_retry", fmt.Sprintf("遇到临时错误(限流或网络波动),%d 秒后第 %d/%d 次重试…", int(backoff.Seconds()), attemptNo, maxAttempts), map[string]interface{}{
|
||||
errorKind, errorSummary := einoTransientRunErrorUserDetail(runErr)
|
||||
progress("eino_run_retry", fmt.Sprintf("遇到临时错误,%d 秒后第 %d/%d 次重试。原因:%s", int(backoff.Seconds()), attemptNo, maxAttempts, errorSummary), map[string]interface{}{
|
||||
"conversationId": conversationID,
|
||||
"source": "eino",
|
||||
"orchestration": orchMode,
|
||||
"error": runErr.Error(),
|
||||
"errorKind": errorKind,
|
||||
"errorSummary": errorSummary,
|
||||
"attempt": attemptNo,
|
||||
"maxAttempts": maxAttempts,
|
||||
"backoffSec": int(backoff.Seconds()),
|
||||
@@ -601,7 +604,12 @@ func runEinoADKAgentLoop(ctx context.Context, args *einoADKRunLoopArgs, baseMsgs
|
||||
"conversationId": conversationID,
|
||||
"source": "eino",
|
||||
"orchestration": orchMode,
|
||||
"error": runErr.Error(),
|
||||
"errorKind": errorKind,
|
||||
"errorSummary": errorSummary,
|
||||
"attempt": attemptNo,
|
||||
"maxAttempts": maxAttempts,
|
||||
"backoffSec": int(backoff.Seconds()),
|
||||
"contextSource": string(ctxSource),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -94,6 +94,84 @@ func isRetryableHTTPStatus(status int) bool {
|
||||
}
|
||||
}
|
||||
|
||||
func einoTransientRunErrorUserDetail(err error) (kind, summary string) {
|
||||
if err == nil {
|
||||
return "", ""
|
||||
}
|
||||
msg := strings.TrimSpace(err.Error())
|
||||
lower := strings.ToLower(msg)
|
||||
if status := httpStatusFromErrorText(lower); status > 0 {
|
||||
switch {
|
||||
case status == 429:
|
||||
kind = "rate_limit"
|
||||
case status == 408 || status == 409 || status == 425:
|
||||
kind = "retryable_http"
|
||||
case status >= 500 && status <= 599:
|
||||
kind = "upstream_server"
|
||||
default:
|
||||
kind = "http_error"
|
||||
}
|
||||
} else {
|
||||
var apiErr *einoopenai.APIError
|
||||
if errors.As(err, &apiErr) && apiErr.HTTPStatusCode > 0 {
|
||||
switch {
|
||||
case apiErr.HTTPStatusCode == 429:
|
||||
kind = "rate_limit"
|
||||
case apiErr.HTTPStatusCode == 408 || apiErr.HTTPStatusCode == 409 || apiErr.HTTPStatusCode == 425:
|
||||
kind = "retryable_http"
|
||||
case apiErr.HTTPStatusCode >= 500 && apiErr.HTTPStatusCode <= 599:
|
||||
kind = "upstream_server"
|
||||
default:
|
||||
kind = "http_error"
|
||||
}
|
||||
}
|
||||
}
|
||||
if kind == "" {
|
||||
switch {
|
||||
case strings.Contains(lower, "too many requests") ||
|
||||
strings.Contains(lower, "rate limit") ||
|
||||
strings.Contains(lower, "rate_limit") ||
|
||||
strings.Contains(lower, "ratelimit"):
|
||||
kind = "rate_limit"
|
||||
case strings.Contains(lower, "overloaded") ||
|
||||
strings.Contains(lower, "capacity") ||
|
||||
strings.Contains(lower, "temporarily unavailable") ||
|
||||
strings.Contains(lower, "service unavailable"):
|
||||
kind = "upstream_busy"
|
||||
case strings.Contains(lower, "connection reset") ||
|
||||
strings.Contains(lower, "connection refused") ||
|
||||
strings.Contains(lower, "connection closed") ||
|
||||
strings.Contains(lower, "i/o timeout") ||
|
||||
strings.Contains(lower, "no such host") ||
|
||||
strings.Contains(lower, "network is unreachable") ||
|
||||
strings.Contains(lower, "broken pipe") ||
|
||||
strings.Contains(lower, "read tcp") ||
|
||||
strings.Contains(lower, "write tcp") ||
|
||||
strings.Contains(lower, "dial tcp") ||
|
||||
strings.Contains(lower, "tls handshake timeout") ||
|
||||
strings.Contains(lower, "goaway") ||
|
||||
strings.Contains(lower, "unexpected eof"):
|
||||
kind = "network"
|
||||
case strings.Contains(lower, "stream error") ||
|
||||
strings.Contains(lower, "unexpected end of json"):
|
||||
kind = "stream"
|
||||
default:
|
||||
kind = "transient"
|
||||
}
|
||||
}
|
||||
return kind, einoTrimRetryErrorSummary(msg)
|
||||
}
|
||||
|
||||
func einoTrimRetryErrorSummary(msg string) string {
|
||||
msg = strings.Join(strings.Fields(strings.TrimSpace(msg)), " ")
|
||||
const maxRunes = 500
|
||||
runes := []rune(msg)
|
||||
if len(runes) <= maxRunes {
|
||||
return msg
|
||||
}
|
||||
return string(runes[:maxRunes]) + "..."
|
||||
}
|
||||
|
||||
func httpStatusFromErrorText(msg string) int {
|
||||
match := httpStatusInErrorPattern.FindStringSubmatch(msg)
|
||||
if len(match) != 2 {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -62,6 +63,45 @@ func TestEinoTransientRetryBackoff(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestEinoTransientRunErrorUserDetail(t *testing.T) {
|
||||
t.Parallel()
|
||||
cases := []struct {
|
||||
name string
|
||||
err error
|
||||
wantKind string
|
||||
}{
|
||||
{"rate limit", errors.New("HTTP 429 Too Many Requests"), "rate_limit"},
|
||||
{"upstream", errors.New("upstream returned 503"), "upstream_server"},
|
||||
{"network", errors.New("read tcp: connection reset by peer"), "network"},
|
||||
{"stream", errors.New("unexpected end of JSON"), "stream"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
kind, summary := einoTransientRunErrorUserDetail(tc.err)
|
||||
if kind != tc.wantKind {
|
||||
t.Fatalf("kind=%q, want %q", kind, tc.wantKind)
|
||||
}
|
||||
if summary == "" {
|
||||
t.Fatal("summary should not be empty")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEinoTrimRetryErrorSummary(t *testing.T) {
|
||||
t.Parallel()
|
||||
raw := strings.Repeat("报错 ", 260)
|
||||
got := einoTrimRetryErrorSummary(raw)
|
||||
if len([]rune(got)) > 503 {
|
||||
t.Fatalf("summary too long: %d runes", len([]rune(got)))
|
||||
}
|
||||
if !strings.HasSuffix(got, "...") {
|
||||
t.Fatal("trimmed summary should end with ellipsis")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEinoMessagesForRunRestart(t *testing.T) {
|
||||
t.Parallel()
|
||||
base := []adk.Message{schema.UserMessage("hi")}
|
||||
|
||||
Reference in New Issue
Block a user