fix(runner): 修复转存后残留二进制误判
统一结果二进制探测与上传规则,避免将 thinking_bytes 等上游元数据误判为待转存媒体,同时保留显式媒体字段和签名识别。\n\n补充不含原始内容的安全诊断,并兼容对象存储前缀旧字段;修正真实 OSS 验收脚本使用的正式字段。\n\n验证:Go 全量测试、go vet、迁移安全检查、真实 Gemini 上游响应及阿里云 OSS 转存均通过。
This commit is contained in:
@@ -306,9 +306,17 @@ func (s *Service) finalizeGeneratedAssets(
|
||||
if !TaskResultHasInlineBinary(next) {
|
||||
return next, nil
|
||||
}
|
||||
diagnostics := taskResultInlineBinaryDiagnostics(next)
|
||||
if s.logger != nil {
|
||||
s.logger.Error("generated result still contains inline binary after object storage materialization",
|
||||
"taskID", taskID,
|
||||
"remainingInlineBinary", diagnostics,
|
||||
)
|
||||
}
|
||||
return nil, &clients.ClientError{
|
||||
Code: "storage_write_failed",
|
||||
Message: "generated binary result could not be written to object storage",
|
||||
Details: map[string]any{"scope": "gateway_result_storage", "remainingInlineBinary": diagnostics},
|
||||
StatusCode: http.StatusServiceUnavailable,
|
||||
Retryable: true,
|
||||
}
|
||||
@@ -417,24 +425,19 @@ func (s *Service) uploadGeneratedBinaryValue(ctx context.Context, taskID string,
|
||||
}
|
||||
|
||||
func generatedRawInlineMediaAsset(key string, value string, siblings map[string]any, taskKind string) (*generatedInlineAsset, bool) {
|
||||
raw := strings.TrimSpace(value)
|
||||
if raw == "" {
|
||||
return nil, false
|
||||
}
|
||||
keyLooksLikeMediaPayload := generatedRawDataMediaPayloadKey(key)
|
||||
contentType := firstNonEmptyString(mediaContentTypeFromItem(siblings), defaultContentTypeForRawMediaKey(key))
|
||||
if !keyLooksLikeMediaPayload && !generatedContentTypeIsMedia(contentType) && !generatedContentTypeIsDocument(contentType) &&
|
||||
!strings.HasPrefix(strings.ToLower(raw), "data:") && len(raw) < localBinaryGenericBase64MinLength {
|
||||
return nil, false
|
||||
}
|
||||
payload, payloadContentType, ok, err := inlineMediaPayload(raw, keyLooksLikeMediaPayload)
|
||||
if err != nil || !ok || len(payload) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
contentType = firstNonEmptyString(payloadContentType, contentType, detectGeneratedAssetContentType(payload))
|
||||
if !generatedContentTypeIsMedia(contentType) && !generatedContentTypeIsDocument(contentType) {
|
||||
return nil, false
|
||||
payload, contentType, _, ok := localBinaryStringBytes(key, value, siblings)
|
||||
if !ok {
|
||||
contentType = firstNonEmptyString(mediaContentTypeFromItem(siblings), defaultContentTypeForRawMediaKey(key))
|
||||
if !generatedContentTypeIsMedia(contentType) && !generatedContentTypeIsDocument(contentType) {
|
||||
return nil, false
|
||||
}
|
||||
var err error
|
||||
payload, _, ok, err = inlineMediaPayload(value, false)
|
||||
if err != nil || !ok || len(payload) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
contentType = firstNonEmptyString(contentType, detectGeneratedAssetContentType(payload))
|
||||
kind := mediaKindForAsset(taskKind, siblings, key, contentType)
|
||||
return &generatedInlineAsset{
|
||||
Bytes: payload,
|
||||
|
||||
Reference in New Issue
Block a user