fix(runtime): 上游错误体统一走 trace.UpstreamError,正文不进 error
M41 的「LLM / embedding / 视觉 上游错误体」一族(M38 #5 #6 #7 #8 #9 #14): 非 2xx 时把响应体截断后拼进 error,而 error 会被 chat run / loop step / retrieve_fallback 打日志,等于把她的提问、记忆正文、要念的台词写进日志。 - model:openai/anthropic 两处 upstreamError 收口到 upstream.go 的 providerUpstreamError;anthropic 流内 error 事件的 evt.Error.Message (原本无上限)整段丢弃,只保留令牌形状的 type - embedding:readErrorBody 删除,改走 helper(input 就是她的记忆正文) - vision:错误路径不再沿用取图的 50 MiB 上限,改为 4 KiB 有界读且不拼原文 - voice:classifyDashscopeStatus 只解 code/request_id,正文只留在内存里做 分类判据;错误体读取同样改为 4 KiB 有界 - 测试:五个上游各一条「日志/error 里搜不到哨兵正文」用例,且能变异打红
This commit is contained in:
1 parent
46a6da13e0
commit
66dda084cd
16 files changed
+570
-183
No files matched your search
@@ -5,7 +5,6 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strings"
|
||||
@@ -314,7 +313,7 @@ func (a *AnthropicChatAdapter) streamOnce(ctx context.Context, req Request, onEv
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return Response{}, a.upstreamError(resp)
|
||||
}
|
||||
return scanAnthropicSSE(resp.Body, onEvent)
|
||||
return scanAnthropicSSE(upstreamLabel(a.name, a.baseURL), resp.Body, onEvent)
|
||||
}
|
||||
|
||||
// resolveModel 返回实际生效的模型名。
|
||||
@@ -404,9 +403,10 @@ func (a *AnthropicChatAdapter) doRequest(httpReq *http.Request, stream bool) (*h
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// upstreamError 把一次非 2xx 响应交给包内唯一的上游错误收口(见 upstream.go):
|
||||
// 只留 status / code / type 与体积摘要,响应体正文与 error.message 不出镜。
|
||||
func (a *AnthropicChatAdapter) upstreamError(resp *http.Response) error {
|
||||
snippet, _ := io.ReadAll(io.LimitReader(resp.Body, errBodyCap))
|
||||
return fmt.Errorf("model: %w: status %d: %s", ErrUpstream, resp.StatusCode, strings.TrimSpace(string(snippet)))
|
||||
return providerUpstreamError(a.name, a.baseURL, resp)
|
||||
}
|
||||
|
||||
// record 上报一次成功调用的用量:先记一条结构化用量日志(含缓存命中率,
|
||||
|
||||
Reference in new issue
Block a user