@@ -8,8 +8,11 @@ import (
88)
99
1010var (
11- requestIDPattern = regexp .MustCompile (`(?i)(?:request[_\s-]?id|x-api-request-id|x-oneapi-request-id)\s*[:=]\s*([A-Za-z0-9._:-]+)` )
12- httpStatusPattern = regexp .MustCompile (`(?i)(?:gemini|openai)\s+http\s+(\d{3})` )
11+ requestIDPattern = regexp .MustCompile (`(?i)(?:request[_\s-]?id|x-api-request-id|x-oneapi-request-id)\s*[:=]\s*([A-Za-z0-9._:-]+)` )
12+ httpStatusPatterns = []* regexp.Regexp {
13+ regexp .MustCompile (`(?i)\b(?:[a-z0-9._/-]+\s+)?http\s+(\d{3})\b` ),
14+ regexp .MustCompile (`(?i)\bstatus(?:\s+code)?\s*[:=]?\s*(\d{3})\b` ),
15+ }
1316)
1417
1518type ErrorSummary struct {
@@ -42,11 +45,7 @@ func SummarizeErrorMessage(message string) ErrorSummary {
4245 UserMessage : "生成失败,请稍后重试。" ,
4346 }
4447
45- if match := httpStatusPattern .FindStringSubmatch (rawMessage ); len (match ) == 2 {
46- if status , err := strconv .Atoi (match [1 ]); err == nil {
47- summary .HTTPStatus = status
48- }
49- }
48+ summary .HTTPStatus = extractHTTPStatus (rawMessage )
5049
5150 set := func (code , category , userMessage string , retryable bool ) {
5251 summary .Type = code
@@ -71,35 +70,37 @@ func SummarizeErrorMessage(message string) ErrorSummary {
7170 set ("prompt_optimize_model_missing" , "local_config" , "默认提示词优化缺少可用的对话模型,请先在设置中补全并保存。" , false )
7271 case strings .Contains (raw , "未找到指定的 provider" ):
7372 set ("prompt_optimize_provider_missing" , "local_config" , "默认提示词优化对应的对话模型配置不存在,请先在设置中补全并保存。" , false )
73+ case summary .HTTPStatus == 0 && (strings .Contains (raw , "permission denied" ) || strings .Contains (raw , "operation not permitted" )):
74+ set ("local_permission_denied" , "local_storage" , "本地文件或目录没有写入权限,请检查保存路径、磁盘权限或系统授权。" , false )
7475 case strings .Contains (raw , "未在响应中找到图片数据" ):
7576 summary .Detail = extractTextResponse (rawMessage )
7677 if summary .Detail != "" || strings .Contains (raw , "安全警告" ) || strings .Contains (raw , "无法" ) || strings .Contains (raw , "抱歉" ) {
7778 set ("policy_blocked" , "upstream_policy" , "上游返回了文本但没有图片,可能触发了安全或合规限制。请调整提示词或参考图后重试。" , false )
7879 } else {
7980 set ("no_image_data" , "upstream_response" , "上游已返回响应,但里面没有图片数据。请稍后重试。" , true )
8081 }
81- case summary .HTTPStatus == 400 :
82- set ("bad_request" , "upstream_request" , "请求参数不被上游接受,请检查提示词、模型或图片参数。" , false )
83- case summary .HTTPStatus == 401 || strings .Contains (raw , "unauthorized" ) || strings .Contains (raw , "invalid api key" ):
84- set ("auth_failed" , "upstream_auth" , "上游鉴权失败,请检查 API Key 是否正确。" , false )
85- case summary .HTTPStatus == 403 || strings .Contains (raw , "quota" ):
86- if strings .Contains (raw , "quota" ) {
87- set ("quota_exceeded" , "upstream_quota" , "上游额度不足或已被限制,请检查账户余额、套餐或权限。" , false )
88- } else {
89- set ("forbidden" , "upstream_auth" , "上游拒绝了本次请求,请检查权限、模型可用性或账户状态。" , false )
90- }
82+ case strings .Contains (raw , "insufficient_quota" ), strings .Contains (raw , "quota exceeded" ), strings .Contains (raw , "额度不足" ), strings .Contains (raw , "余额不足" ):
83+ set ("quota_exceeded" , "upstream_quota" , "上游额度不足或已被限制,请检查账户余额、套餐或权限。" , false )
84+ case summary .HTTPStatus == 400 || strings .Contains (raw , "bad request" ):
85+ set ("bad_request" , "upstream_request" , "请求格式或参数不被上游接受,请检查提示词、模型、图片参数或请求内容。" , false )
86+ case summary .HTTPStatus == 401 || strings .Contains (raw , "unauthorized" ) || strings .Contains (raw , "invalid api key" ) || strings .Contains (raw , "api key" ) && strings .Contains (raw , "invalid" ) || strings .Contains (raw , "token expired" ) || strings .Contains (raw , "令牌过期" ):
87+ set ("unauthorized" , "upstream_auth" , "上游鉴权失败,请检查 API Key、令牌是否正确,或是否已过期。" , false )
88+ case summary .HTTPStatus == 403 || strings .Contains (raw , "forbidden" ) || strings .Contains (raw , "权限不足" ) || strings .Contains (raw , "insufficient permissions" ):
89+ set ("forbidden" , "upstream_permission" , "上游拒绝了本次请求,一般是权限不足、账户受限或模型无权访问。" , false )
9190 case summary .HTTPStatus == 404 || strings .Contains (raw , "not found" ):
92- set ("model_not_found " , "upstream_request" , "请求的模型或接口不存在,请检查模型配置 。" , false )
91+ set ("not_found " , "upstream_request" , "请求的资源未找到,可能是模型、接口地址或上游端点不存在 。" , false )
9392 case summary .HTTPStatus == 408 :
94- set ("upstream_timeout" , "upstream_network" , "上游等待超时,图片结果未能及时返回。请稍后重试。" , true )
95- case summary .HTTPStatus == 429 || strings .Contains (raw , "too many requests" ) || strings .Contains (raw , "负载已饱和" ) || strings .Contains (raw , "overloaded" ):
93+ set ("request_timeout" , "upstream_network" , "上游等待超时,图片结果未能及时返回。请稍后重试。" , true )
94+ case summary .HTTPStatus == 413 || strings .Contains (raw , "request entity too large" ) || strings .Contains (raw , "payload too large" ) || strings .Contains (raw , "content too large" ) || strings .Contains (raw , "请求体太大" ):
95+ set ("request_too_large" , "upstream_request" , "请求体过大,请减少图片体积、参考图数量,或缩短过长的输入内容后重试。" , false )
96+ case summary .HTTPStatus == 429 || strings .Contains (raw , "too many requests" ) || strings .Contains (raw , "rate limit" ) || strings .Contains (raw , "负载已饱和" ) || strings .Contains (raw , "overloaded" ):
9697 set ("rate_limited" , "upstream_capacity" , "上游当前较忙或触发限流,请稍后再试。" , true )
97- case summary .HTTPStatus == 500 :
98- set ("upstream_internal_error " , "upstream_server" , "上游服务内部异常,请稍后重试。" , true )
98+ case summary .HTTPStatus == 500 || strings . Contains ( raw , "internal server error" ) :
99+ set ("internal_server_error " , "upstream_server" , "上游服务内部异常,这通常是服务端问题 ,请稍后重试。" , true )
99100 case summary .HTTPStatus == 502 || strings .Contains (raw , "bad gateway" ):
100101 set ("bad_gateway" , "upstream_gateway" , "上游网关异常,结果没有正常回传。请稍后重试。" , true )
101- case summary .HTTPStatus == 503 :
102- set ("service_unavailable" , "upstream_gateway " , "上游服务暂时不可用,请稍后重试。" , true )
102+ case summary .HTTPStatus == 503 || strings . Contains ( raw , "service unavailable" ) || strings . Contains ( raw , "temporarily unavailable" ) || strings . Contains ( raw , "维护中" ) :
103+ set ("service_unavailable" , "upstream_server " , "上游服务暂时不可用,可能在维护或过载中 ,请稍后重试。" , true )
103104 case summary .HTTPStatus == 504 :
104105 set ("gateway_timeout" , "upstream_gateway" , "上游网关等待超时,结果没有及时回传。请稍后重试。" , true )
105106 case strings .Contains (raw , "tls" ):
@@ -117,6 +118,20 @@ func SummarizeErrorMessage(message string) ErrorSummary {
117118 return summary
118119}
119120
121+ func extractHTTPStatus (message string ) int {
122+ for _ , pattern := range httpStatusPatterns {
123+ match := pattern .FindStringSubmatch (message )
124+ if len (match ) != 2 {
125+ continue
126+ }
127+ status , err := strconv .Atoi (match [1 ])
128+ if err == nil {
129+ return status
130+ }
131+ }
132+ return 0
133+ }
134+
120135func UserFacingMessage (summary ErrorSummary ) string {
121136 message := strings .TrimSpace (summary .UserMessage )
122137 if message == "" {
0 commit comments