feat(channel): 对齐 vivid 最新渠道/模型管理设计
渠道管理(对齐 9db9971/9f6eeca/b607a8d/268a8f7/7f8a87e): - 列表新增「运行中」(Redis 并发槽位实时计数,与调度同源)和「失败数」 (event_logs 按渠道聚合)两列 - 行内「同步上游模型」恢复弹窗:默认全开、右侧开关、彩点+单行别名, 底部「同步模型」批量导入;编辑表单去掉获取模型列表按钮(保存已自动 全量同步);去掉勾选即解绑语义与 unbind-model 端点 - 导入加固:别名与上游同名报错、同批别名复用拒绝、本地类型冲突拒绝、 单次上限 50 模型管理(对齐 5545195): - 模型表单/CreateModel 补齐 max_reference_videos/audios 与 max_ref_video/audio_seconds 透传 产物(对齐 2253e58): - 下载结果仅信任 image/*/video/* 响应头,text/plain 等乱报一律按魔数 嗅探定 MIME Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
@@ -422,8 +422,13 @@ func (c *Client) Download(ctx context.Context, url string) ([]byte, string, erro
|
||||
if len(data) == 0 {
|
||||
return nil, "", fmt.Errorf("%w: empty result", ErrRetryable)
|
||||
}
|
||||
// Content-Type fallback chain: only trust image/* video/* headers (upstreams
|
||||
// often mislabel results text/plain or octet-stream), else sniff magic bytes.
|
||||
ct := strings.TrimSpace(resp.Header.Get("Content-Type"))
|
||||
if ct == "" || ct == "application/octet-stream" {
|
||||
if i := strings.IndexByte(ct, ';'); i >= 0 {
|
||||
ct = strings.TrimSpace(ct[:i])
|
||||
}
|
||||
if !strings.HasPrefix(ct, "image/") && !strings.HasPrefix(ct, "video/") {
|
||||
ct = http.DetectContentType(data)
|
||||
}
|
||||
return data, ct, nil
|
||||
|
||||
Reference in New Issue
Block a user