fix: address review — fail loud on non-video bodies, dedupe form plumbing, doc parity
- videoMIME no longer hard-falls-back to video/mp4: a 2xx body that is neither declared nor sniffable as video (JSON job envelope, HTML error page) is now an APIError instead of a 'successful' corrupt clip. - Resolution rides the wire as width/height AND the OpenAI-style size string, so either upstream convention honors an explicit request. - writeFormFields + mimeFromContentType shared helpers replace the copied multipart loop (audio.go/video.go) and Content-Type branch. - ADR-0019 indexed in docs/adr/README.md; README gains the videogen section + support-matrix mention (docs-parity rule). Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01AXQxVhXBw8PwFAtsVrXSmj
This commit is contained in:
@@ -30,6 +30,8 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
@@ -280,3 +282,34 @@ func (p *Provider) apiError(resp *http.Response, model string) error {
|
||||
e.Message = strings.TrimSpace(string(body))
|
||||
return e
|
||||
}
|
||||
|
||||
// formField is one multipart form entry for the media endpoints. Required
|
||||
// fields always go on the wire (an empty model id should fail loudly
|
||||
// upstream, not silently vanish); optional ones only when set.
|
||||
type formField struct {
|
||||
key, value string
|
||||
required bool
|
||||
}
|
||||
|
||||
// writeFormFields appends fields to a multipart writer, skipping unset
|
||||
// optional entries. wrap labels errors ("build transcription form", ...).
|
||||
func writeFormFields(w *multipart.Writer, wrap string, fields []formField) error {
|
||||
for _, f := range fields {
|
||||
if !f.required && f.value == "" {
|
||||
continue
|
||||
}
|
||||
if err := w.WriteField(f.key, f.value); err != nil {
|
||||
return fmt.Errorf("llama-swap: %s: %w", wrap, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// mimeFromContentType returns the parsed media type when it matches prefix
|
||||
// ("audio/", "video/"), else "".
|
||||
func mimeFromContentType(contentType, prefix string) string {
|
||||
if mt, _, err := mime.ParseMediaType(contentType); err == nil && strings.HasPrefix(mt, prefix) {
|
||||
return mt
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user