fix(knowledge): always retry source fetch via lightpanda on trigger status
Backend CI / Backend (push) Successful in 15m15s

LinkReader 500 (or other trigger_status) used to be gated by an extra
allowed_domains whitelist on the tenant API side, so URLs like
m.baidu.com/bh/m/detail/... fell straight through to the user with a raw
"webpage parser failed" message. Drop the whitelist gate — enabled +
trigger_status is enough — and surface a friendly Chinese prompt when
both LinkReader and the lightpanda fallback give up. Full error chain
is kept in the logger for debugging.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-11 19:48:21 +08:00
parent 83c5cc76d6
commit f06c8dfc01
2 changed files with 65 additions and 18 deletions
@@ -58,6 +58,21 @@ func isSourceFetchRestrictedError(err error) bool {
return errors.As(err, &restricted)
}
// sourceFetchExhaustedError 表示 LinkReader 和 lightpanda 兜底都失败,应返回用户友好提示。
type sourceFetchExhaustedError struct {
URL string
Primary error
Fallback error
}
func (e sourceFetchExhaustedError) Error() string {
return "源文章解析失败,请更换链接或确认链接可公开访问(已尝试浏览器渲染兜底)"
}
func (e sourceFetchExhaustedError) Unwrap() error {
return e.Primary
}
type arkToolExecuteRequest struct {
ActionName string `json:"action_name"`
ToolName string `json:"tool_name"`
@@ -96,9 +111,10 @@ func (s *KnowledgeService) parseWebsiteKnowledge(ctx context.Context, rawURL str
s.logger.Warn("knowledge browser fetch fallback failed",
zap.String("url", rawURL),
zap.Error(fallbackErr),
zap.NamedError("primary", err),
)
}
return nil, classifySourceFetchError(rawURL, fmt.Errorf("%w; browser fetch fallback failed: %v", err, fallbackErr))
return nil, sourceFetchExhaustedError{URL: rawURL, Primary: err, Fallback: fallbackErr}
}
text := normalizeKnowledgeText(item.Content)
@@ -287,9 +303,6 @@ func (s *KnowledgeService) shouldTryBrowserFetchFallback(rawURL string, err erro
if !browserCfg.Enabled {
return false
}
if !browserFetchDomainAllowed(rawURL, browserCfg.AllowedDomains) {
return false
}
status := extractHTTPStatusFromError(err)
if status <= 0 {
return false